2016-08-31 3 views
2

У меня есть $ FILEAWK: загадочная двойная линия печати

1 textline1 
1 textline2 
1 textline3 
1 textline4 

Я хочу найти textline3 и сделать сумму: 1stcolumn + 1

LINENUMBER является:

lnr=$(grep -n textline3 $FILE | cut -d : -f1) 

Но когда i использовать awk:

awk -v l="$lnr" 'FNR==l{ sub($1,$1 + 1); print }1' $FILE 

Я получаю ошибочная (3-я строка печатается дважды)

1 textline1 
1 textline2 
2 textline3 
2 textline3 
1 textline4 
+3

Удалить 'print'? – Inian

+0

@jods Если какой-либо из следующих ответов помог вам, пожалуйста, примите ответ, отметив правильный знак рядом с ответом за его надлежащее закрытие. благодаря –

ответ

6

Причина двойной печати: вы печатаете внутри {} и используете 1 также. 1 означает true, а поведение по умолчанию awk - печать.

awk -v l="$lnr" 'FNR==l{ sub($1,$1 + 1)}1' $FILE 
4

Вы можете избежать использования grep и пусть awk сделать магию.

awk '/textline3/{sub($1,$1 + 1)}1' file 
1 textline1 
1 textline2 
2 textline3 
1 textline4 

В общем, вы можете сделать awk '/<pattern>/ { <action> }' file для манипуляции.

0

Решение с использованием perl

$ perl -pe 's/^(\d+)(?=\s*textline3)/$1+1/e' $FILE 
1 textline1 
1 textline2 
2 textline3 
1 textline4 

или

perl -pe 's/^(\d+)/$1+1/e if /textline3/' $FILE 
1

Если вы просто хотите, чтобы увеличить первое поле на N й линии, просто так сказать:

$ awk -v line=3 'FNR==line {$1+=1}1' file # line is more readable than l 
1 textline1 
1 textline2 
2 textline3 
1 textline4 

Обратите внимание, что 1 здесь t riggering awk - действие по умолчанию, состоящее в печати текущей строки. Для каждой строки будет напечатано начальное значение, но для номера строки line оно напечатает значение 1 st с его значением +1.

И поэтому вы видите эту строку дважды в своем коде: потому что в действии, вызванном FNR==line, вы уже звоните print.

1

Theres несколько проблем с вашего скрипта:

  1. Специфическая ошибка вы спрашиваете: Вы звоните print внутри блока действий и затем 1 в конце сценария является постоянным истинным условием что приведет к тому, что awk выполнит действие по умолчанию для повторной печати записи.
  2. Никогда не используйте букву l (el) как имя переменной, она выглядит слишком сильно, как номер 1 (один), и поэтому ваш код становится более трудным для чтения.
  3. Вам не нужен вызов функции для изменения $1, просто сделайте $1++ (предполагая, что textline3 не содержит цепочки белого пространства, которые не должны быть объединены в один пустой символ).
  4. Вам не нужно использовать grep + wc для поиска строк, просто держите его в awk.
  5. В общем случае вам следует избегать использования входных данных (например, $1) как строки поиска или замены строки любой команды * sub(), так как это приведет к сбою при использовании различных метасимволов regexp или backreference на входе.

Так что ваш сценарий должен быть просто:

$ awk '/textline3/{$1++}1' file 
1 textline1 
1 textline2 
2 textline3 
1 textline4 
Смежные вопросы