Заменить строку, только если в следующей строке есть другая указанная строка c - PullRequest
0 голосов
/ 04 мая 2020

Я пытаюсь заменить строку в строке, только если в следующей строке указана c строка.

У меня есть:

13963   12602   gene
13963   12602   rRNA

И результат должен быть

13963   12602   rRNA
13963   12602   rRNA

Где цифры меняются ... Итак, я попытался:

VAR_1=$1

if [grep rRNA -B1  $1 |awk '{print $3}' |head -n1 ='gene']
 then
   sed 's/gene/rRNA'
fi

И я получаю

line 5: [grep: command not found
head: =gene]: No such file or directory

И я не совсем знаю, откуда go отсюда ...

Ответы [ 3 ]

3 голосов
/ 04 мая 2020

Не могли бы вы попробовать, написать и протестировать только с показанными образцами.

awk '
FNR==NR{
  if($NF=="rRNA"){
    a[FNR]=$NF
  }
  next
}
((FNR+1) in a){
  $NF=a[FNR+1]
}
1
'  Input_file  Input_file | column -t

ИЛИ, если вы хотите иметь переменную в awk, где вы можете определить строку для просмотра в Input_file, а затем попробуйте следующее.

awk -v str="rRNA" '
FNR==NR{
  if($NF==str){
    a[FNR]=$NF
  }
  next
}
((FNR+1) in a){
  $NF=a[FNR+1]
}
1
'  Input_file  Input_file | column -t

Логическое объяснение:

  • Чтение Input_file здесь 2 раза.
  • Когда Input_file читается первый раз, тогда он ищет те строки, которые имеют строку рРНК в своем последнем поле.
  • Затем он создает массив, индекс которого равен этому номеру строки, а значение - последнее поле этой строки.
  • next пропустит все дальнейшие операторы
  • Теперь проверяем условие (FNR+1) in a, которое будет проверено, когда Input_file будет прочитан во второй раз. Он проверяет, присутствует ли номер текущей строки + 1 в массиве или нет.
  • , если он входит в массив, устанавливает значение массива в последнее поле текущей строки
  • 1 будет печатать строки.
0 голосов
/ 05 мая 2020

Вот решение sed со следующими допущениями: вы ищете последовательные строки, в которых фиксированные слова gene и rRNA (как полные слова, а не фрагменты слов) появляются в конце первого, соответственно вторую строку, и в этих случаях замените gene на rRNA. Числа, предшествующие этим словам, не играют никакой роли. (Если вместо этого они должны совпадать, это тоже можно упорядочить.)

Сначала взгляните на созданный мной входной файл для проверки особых ситуаций:

$cat ff

13960   12602   gene
13963   12602   rRNA
10030   24022   general
10040   32002   rRNA
30902   32098   gene
34003   30934   gene
40902   30921   rRNA
42093   40023   zymogene
34020           rRNA
30202   10030   para
40302   20030   gene
               crRNA

Здесь gene будет заменить на rRNA ровно на две строки: те, которые начинаются с цифр 13960 и 34003. Обратите внимание, что строка, начинающаяся с 42093 - gene, появляется в конце, но не как полное слово, и ее не следует заменять , Кроме того, последняя строка заканчивается строкой rRNA, но поскольку это фрагмент слова, а не полное слово, gene над ним не следует заменять.

Тогда:

$ sed '{N;s/\bgene\(\n.*\brRNA\)$/rRNA\1/;P;D}' ff

13963   12602   rRNA
13963   12602   rRNA
10030   24022   general
10040   32002   rRNA
30902   32098   gene
34003   30934   rRNA
40902   30921   rRNA
42093   40023   zymogene
34020           rRNA
30202   10030   para
40302   20030   gene
               crRNA

Обработка начинается с первой строки. На каждом шаге: N добавляет новую строку и следующую строку ввода в пространство шаблона; s заменяет gene на rRNA, если первая строка заканчивается полным словом gene, а вторая заканчивается полным словом rRNA (обратите внимание на использование утверждения \b); P печатает первую строку из пространства шаблона (независимо от того, была ли она оставлена ​​без изменений или подверглась замене gene <- <code>rRNA); D затем удаляет эту первую строку (включая новую строку) из пространства шаблона. Затем цикл начинается снова: N добавляет новую строку и следующую строку ввода в пространство шаблона и т. Д. c. Когда мы достигаем последней строки, N ничего не делает (так как в файле больше нет строк); команда s автоматически не найдет совпадений, P напечатает последнюю строку, D удалит ее, и все готово. Обратите внимание, что в стандарте POSIX в последней строке, если N не находит "следующей" строки, sed завершается (и, следовательно, последняя строка не является P набранной); так что это решение в полной мере использует это расширение GNU команды N.

0 голосов
/ 05 мая 2020

Пусть sed рассматривает новые строки как простые символы, это опция -z.
Когда за gene следует новая строка, а на следующей строке (подстрока до следующей новой строки) строка rRNA имеет вид в конце строки замените gene.

sed -rz 's/gene\n([^\n]*)(rRNA\n)/\2\1\2/g' "$1"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...