我有一个输入文件,其中多个段落至少有两个换行符(\n\n
),我想从某些段落中的行中提取字段。我认为如果我能让gensub
按照我的希望工作,那么处理将是最简单的。考虑以下输入文件:
[Record R1]
Var1=0
Var2=20
Var3=5
[Record R2]
Var1=10
Var3=9
Var4=/var/tmp/
Var2=12
[Record R3]
Var1=2
Var3=5
Var5=19
我想从记录Var2
和R1
(其中R3
实际上并不存在)中仅打印Var2
的值。我可以通过设置RS="\n\n"
轻松地将所有变量分组到相应的记录中,然后它们都包含在$0
中。但是因为我不知道它会在哪里出现在列表中,所以我想使用像gensub这样的东西来提取它。这就是我要做的事情:
awk '
BEGIN {
RS="\n\n"
}
/Record R1/ || /Record R3/ {
print gensub(/[\n.]*Var2=(.*)[\n.]*/, "\\1", "g", $0)
}
' /tmp/input.txt
但它不是仅打印20
(来自R1的Var2的值),而是打印以下内容:
[Record R1]
Var1=0
20
Var3=5
[Record R3]
Var1=2
Var3=5
Var5=19
目的是gensub命令中的正则表达式将捕获\n
之前和之后的所有字符(换行符:.
;以及非换行符:Var2=XX
),并用XX
替换所有字符。但相反,它只捕获与Var2=XX
在同一行上的字符。 awk
的gensub
可以做这种多线替换吗?
我知道另一种方法是循环遍历记录中的所有字段,分割与Var2=
符号上的=
匹配的字段,但是当我将其扩展到多个变量时感觉效率较低。
我不明白你想用gensub()做什么,但要做你在任何awk中尝试做的事情是:
awk -F'[][[:space:]=]+' '{f[$2]=$3} !NF{if (f["Record"]~/^R[12]$/) print f["Var2"]; delete f}' file
20
12
awk -F'[][[:space:]=]+' '{f[$2]=$3} !NF{if (f["Record"]~/^R[13]$/) print f["Var2"]; delete f}' file
20
gensub()并不关心它所操作的字符串是一行还是多行btw - \n
只是一个字符,与其他任何字符都没有区别。
哦,坚持下去,现在我看到你在想那个gensub() - 你的问题是:
[\n.]*
的意思是zero or more newlines or periods
,但你的输入中没有任何句号,所以它与\n*
相同,但你在Var2
之前没有任何换行符Var2
在您的第2条记录中不存在,因此正则表达式无法与之匹配。(.*)
将匹配记录结尾的所有内容(最左边的最长匹配)。"g"
具有误导性,因为你只期望1场比赛。所以在多行文本上使用gensub()不是问题,你的正则表示错误。
另一个awk
$ awk -v RS= '/\[Record R[13]\]/{for(i=2;i<=NF;i++)
{v=sub(/ *Var2=/,"",$i);
if(v) print $i}}' file
20