【问题标题】:awk : Match Pattern after certain pattern and Print words next to Patternawk :在特定模式之后匹配模式并在模式旁边打印单词
【发布时间】:2013-05-29 16:52:05
【问题描述】:

如果匹配,我需要匹配一些模式我需要打印接下来的几个单词。我只有三个这样的条件要匹配……但我只需要打印满足第一个条件后出现的那些单词。 . 即..

虽然在 LLL SSS 之前我有 TTT ,但我只需要将 LLL SSS 之后的那些打印到 AAA RRR ,当我遇到 LLL SSS 需要做同样的事情时,我尝试声明一个 awk 标志变量,但是它似乎不起作用。请帮助我。

var1="LLL";var2="SSS";var3="TTT";var4="AAA";var5="RRR";
awk -v flag=1 '{
for (m=1;m<=NF;m++)
if($m~m/'$var1'/ && $(m+1)~/'$var2'/)
print "ABCD: ", $(m+2),$(m+3),$(m+4)
{flag=0};
else {
if {flag==0 && $m~/'var3'/)
print "EFG : ", $(m+1);
else { 
if (flag==0 && $m~/'$var4'/ && $(m+1)~/'var5'/)
print "HIJ: ",$(m+2),$(m+3) 
{flag=1}; 
}
}
}
}' fliename 

我的文件是这样的:

AAA RRR H I
DDDD OOO HI J UGC RR
TTT YYY
LLLLL IIIIII
LLL SSS A B C D
N
DDDD TTT EFG
BBB AAA RRR J K
HHHHHH RRRRRR 
LLL SSS E H G H
N
DDDD TTT EFG
UUUUU BBB AAA RRR J K

【问题讨论】:

  • 你的预期输出是什么?
  • 拥有一个名为flag 的标志就像有一个孩子并将其命名为kid。来吧...还有一些缩进怎么样?
  • 而且,您的代码语法没有多大意义。连编辑都很难。
  • 如果您想将字段与令牌匹配,请不要使用正则表达式。在这种情况下太不准确了。您还可以使用 ENVIRON["var1"] 哈希读取 awk 中的环境变量。您可以测试一个字段匹配,例如 if ($m == ENVIRON["var1"])
  • @glennjackman:你是对的!或致电var1=LLL var2=SSS awk '...'

标签: shell unix awk


【解决方案1】:

当您有多个这样的嵌套ifs 时,使用大括号完全明确非常重要。我已尝试重写您的代码。

  • 使用-v 将shell 变量传递给awk,而不是使用引号
  • 空白是你的朋友——或者更确切地说,它是下一个必须维护你的代码的人的朋友。
  • 修复了脚本第 8 行的几个错误
var1="LLL";var2="SSS";var3="TTT";var4="AAA";var5="RRR";
awk -v flag=1 \
    -v var1="$var1" \
    -v var2="$var2" \
    -v var3="$var3" \
    -v var4="$var4" \
    -v var5="$var5" \
'{
    for (m=1; m<=NF; m++) {
        if ($m ~ var1 && $(m+1) ~ var2) {
            print "ABCD: ", $(m+2),$(m+3),$(m+4)
            flag=0
        }
        else {
            if (flag == 0 && $m ~ var3) {
                print "EFG : ", $(m+1)
            }
            else {
                if (flag == 0 && $m ~ var4 && $(m+1) ~ var5) {
                    print "HIJ: ",$(m+2),$(m+3)
                    flag=1
                }
            }
        }
    }
}' fliename

【讨论】:

  • whitespace is your friend -- or rather it's the friend of the next guy who has to maintain your code+1
  • 在for循环中,最大值是NF-1。如果写非空信息真的很重要,那么NR-4
【解决方案2】:

Glenn 的版本有所改进。我否定了flag,所以可以跳过初始化。

var1="LLL";var2="SSS";var3="TTT";var4="AAA";var5="RRR";
awk -v var1="$var1" -v var2="$var2" -v var3="$var3" -v var4="$var4" -v var5="$var5" \
'!flag {
    for (m=1; m<=NF-1; ++m) 
        if ($m == var1 && $(m+1) == var2) {
            print "ABCD: ", $(m+2),$(m+3),$(m+4)
            flag=1
            next
        }
 }
 flag {
    for (m=1; m<=NF-1; ++m) 
        if ($m == var3) {
            print "EFG : ", $(m+1)
            break
        } else {
            if ($m == var4 && $(m+1) == var5) {
                print "HIJ: ",$(m+2),$(m+3)
                flag=0
                break
            }
        }
}' filename

输出:

ABCD:  A B C
EFG :  EFG
HIJ:  J K
ABCD:  E H G
EFG :  EFG
HIJ:  J K

或者您甚至可以尝试纯 bash 版本:

var1="LLL";var2="SSS";var3="TTT";var4="AAA";var5="RRR";

found=0;
while read -a a; do
  if [ $found -eq 0 ]; then
    for((i=0;((i+1))<${#a[*]};++i)) {
      [ ${a[$i]} == $var1 -a ${a[((i+1))]} == $var2 ] &&
        echo ABCD: ${a[((i+2))]} ${a[((i+3))]} ${a[((i+4))]} &&
        found=1 && break
    }
  else
    for((i=0;((i+1))<${#a[*]};++i)) {
      [ ${a[$i]} == $var3 ] && echo EFG: ${a[((i+1))]} && break
      [ ${a[$i]} == $var4 -a ${a[((i+1))]} == $var5 ] && found=0 &&
        echo HIJ:  ${a[((i+2))]} ${a[((i+3))]} && break
    }
  fi
done <filename

【讨论】:

  • @user2428250:我添加了一个纯bash 解决方案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-01-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-21
  • 2016-01-04
  • 1970-01-01
相关资源
最近更新 更多