Как мне изменить текстовое поле с помощью awk?

#linux #perl #unix #sed #awk

#linux #perl #unix #sed #awk

Вопрос:

Я хочу удалить текст после первого двоеточия : (включительно) или заменить его ничем.

Например, 1:5:30 должно быть изменено на 1 . Я предпочитаю сценарий awk для выполнения этой работы. Но я не знаю, как это сделать. Не могли бы вы, пожалуйста, дать мне какие-либо указания? Заранее спасибо.

Мои данные разделены табуляцией, и файл выглядит так, как будто в некоторых ячейках есть точки.

 1       313     .       T       C       30.11        1:5:30  .       .       .
1       316     .       A       T       30.80        1:5:30  .       0:8:28  .
1       317     .       T       A       31.40        1:5:36  .       0:8:28  .
  

Я попробовал следующее, но со всеми из них у меня ничего не вышло:

 sed 's/:*:*//g' mydatafile
sed 's/:[0-9]:[0-9]//g' mydatafile
  

Комментарии:

1. Похоже, что есть много правильных ответов. Продолжайте и примите одно из них. Нажмите на «галочку», чтобы принять ответ

Ответ №1:

Немного неясно, каким должен быть желаемый результат, но это моя интерпретация, использующая sed :

 $ sed 's/:.*//' input
1   313 .   T   C   30.11   1
1   316 .   A   T   30.80   1
1   317 .   T   A   31.40   1
  

Использование awk:

 $ awk -F":" '{print $1}' input
1   313 .   T   C   30.11   1
1   316 .   A   T   30.80   1
1   317 .   T   A   31.40   1
  

Используя Cut:

 cut -d":" -f1 input
  

Использование bash:

 IFS=':'

while read a b; do
    echo $a
done < input
  

Альтернативная интерпретация с использованием awk:

 $ awk 'BEGIN {OFS="t"} {sub(/:.*/,"",$7); print}' input
1   313 .   T   C   30.11   1   .   .   .
1   316 .   A   T   30.80   1   .   0:8:28  .
1   317 .   T   A   31.40   1   .   0:8:28  .
  

3-е и, надеюсь, последнее обновление

третья интерпретация с использованием awk:

 $ awk 'BEGIN {OFS="t"} {for (i=1;i<NF;i  ){sub(/:.*/,"",$i)}; print}' input
1   313 .   T   C   30.11   1   .   .   .
1   316 .   A   T   30.80   1   .   0   .
1   317 .   T   A   31.40   1   .   0   .
  

Комментарии:

1. Дорогой Фредрик, очень хорошие скрипты sed / bash / awk. Большое спасибо. На самом деле, я хочу, чтобы все ячейки с таким шаблоном (integers_1: integers_2: integers_2) были заменены на integer_1.

2. @jianfeng.mao было бы хорошо, если бы вы могли обновить свой вопрос списком правильных выходных данных. Я сделал 2 интерпретации, и обе были неправильными 😉

Ответ №2:

 perl -p -e 's/:d :d //g' mydatafile
  

Комментарии:

1. Уважаемый FMc, большое спасибо. Я не могу понять perl. Но я узнал, что это мощное средство из вашего скрипта.

Ответ №3:

Попробуйте это:

 sed 's/([0-9][0-9]*):[0-9][0-9]*:[0-9][0-9]*/1/g' infile
  

или

 sed 's/([0-9]{1,}):[0-9]{1,}:[0-9]{1,}/1/g' infile
  

Вывод:

 1       313     .       T       C       30.11        1  .       .       .
1       316     .       A       T       30.80        1  .       0  .
1       317     .       T       A       31.40        1  .       0  .
  

Ответ №4:

Вот самый короткий вариант, использующий sed :

 sed -i.orig 's/([0-9])*:[^ ]*/1/g' inputfile
  

При этом сохраняется копия исходного файла как inputfile.orig . И заменяет файл на месте.

Ответ №5:

Это должно сработать.

 $ sed -e 's/:.*//' mydatafile
1       313     .       T       C       30.11        1
1       316     .       A       T       30.80        1
1       317     .       T       A       31.40        1
  

Я думаю, что sed немного проще, чем awk, для решения этой проблемы.

Обзор синтаксиса регулярных выражений

Позже . . .

Из ваших комментариев к другим ответам я вижу, что вы хотите заменить каждое вхождение x:y:z на x . В таком случае я бы использовал эту awk-программу.

 $ cat test.awk
BEGIN {
  FS = "t";
}
{
  for (i = 1; i <= NF; i  ) {
    if (match($i, /:.*/)) {
        $i = substr($i, 1, RSTART - 1);
    }
    printf("%st", $i);
  }
  printf("n");
}

$ awk -f test.awk test.dat
1       313     .       T       C       30.11   1       .       .       .
1       316     .       A       T       30.80   1       .       0       .
1       317     .       T       A       31.40   1       .       0       .
  

Комментарии:

1. Дорогой Кэтколл, большое спасибо. Я пока пытаюсь понять ваш скрипт.

2. @jianfeng.mao: Он просто заменяет двоеточие, за которым следует ноль или более символов, на ничто.