awk:神秘的双线打印

时间:2016-08-31 13:39:19

标签: bash awk

我有一个$ FILE

1 textline1
1 textline2
1 textline3
1 textline4

我想搜索textline3并制作sum:1stcolumn + 1

Linenumber是:

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

但是当我使用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

5 个答案:

答案 0 :(得分:7)

双重打印的原因是,您在{}内打印并使用1。 1表示true,awk的默认行为是打印。

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

答案 1 :(得分:4)

您可以避免使用grep并让awk发挥魔力。

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

通常,您可以执行awk '/<pattern>/ { <action> }' file操作。

答案 2 :(得分:1)

如果您只想增加N th 行的第一个字段,只需这样说:

$ 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此处触发awk的默认操作,包括打印当前行。对于每一行,它将打印初始值,但对于行号line,它将打印1 st 值,其值为+1。

这就是为什么你在代码中看到两行的原因:因为在FNR==line触发的操作中,你已经在调用print

答案 3 :(得分:1)

你的剧本存在一些问题:

  1. 您询问的具体错误:您在操作块内调用1,然后脚本末尾的l是一个恒定的真实条件,这将导致awk执行它再次打印记录的默认操作。
  2. 绝不使用字母1(el)作为变量名称,它看起来与数字$1(一个)太相似,因此使您的代码更难阅读。
  3. 您不需要更改$1++的函数调用,只需执行textline3(假设$1不包含不能连接成一个空白字符的空格链)。
  4. 您不需要使用grep + wc来查找行,只需将其保存在awk中。
  5. 一般情况下,您应该避免使用输入数据(例如$ awk '/textline3/{$1++}1' file 1 textline1 1 textline2 2 textline3 1 textline4 )作为任何* sub()命令的搜索regexp或替换字符串字段,因为在输入中给定各种正则表达式或反向引用元字符时,这将隐式失败。
  6. 所以你的脚本应该只是:

    while IFS= read -r host && IFS= read -r i <&3; do
        some_command "$host" "$i"
    done < file1 3< file2
    

答案 4 :(得分: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