awk:如何读取输入记录

时间:2016-02-05 11:47:43

标签: bash shell awk scripting

我想从input1.txt读取值。根据读取的值,我将对input2.xml采取措施 我正在调用我的awk脚本,

$bash: awk -f myAwk.awk input1.txt input2.xml

$bash: cat myAwk.awk
{
print $0;
}

/<record / { i=1 }
i { a[i++]=$0 }
/<\/record>/ {
    if (found) {
       //Do some action
    }
    i=0;
    found=0
}
/SEARCH { found=1 }

$bash: cat input1.txt
SEARCH
DONTSEARCH

问题是

1:当我调用我的awk脚本时,它是标准输出上input2.xml的引用值。

2:如何遍历input1.txt中的每个值并将其放在SEARCH中?

3 个答案:

答案 0 :(得分:2)

对于特定情况,您需要将行更改为:

NR==FNR && /SEARCH/ { found=1 }

但也许,根据您的需要,更简单的方法就是:

awk -f myAwk.awk found=1 input2.xml

也就是说,您可以在脚本之外的命令行上设置变量。那么你根本不需要/ SEARCH /行......

答案 1 :(得分:1)

当你想要

  • 将第一个文件读入内存,然后
  • 处理第二个文件,

awk中的规范构造沿着

FNR=NR {
  # read stuff from the first file, perhaps store it in an array.
  next;
}

{
  # read the second file, do things to it.
}

变量NR是awk已处理的当前记录数(行数),FNR是当前文件中已处理的当前记录数。当你进入第一个文件时,它们是相同的。

您的脚本正在打印input2.xml的内容,因为脚本中的第一个语句告诉它完全按照print $0进行操作。这可以简化为print。或者整个括号内的陈述可以替换为1

您的问题中未包含样本数据或预期输出,因此我只能猜测您 想要在此处实现的内容。 (特别是,您没有解释您尝试使用ai变量做什么。)也许您想要的更多内容如下:

# Set a semaphore for later use, only if "SEARCH" is in the first file.
NR==FNR && /^SEARCH/ {
  found=1
}
# Also, store everything from the first file in an array.
NR==FNR {
  array[NR]=$0
  next
}

/<record / {
  # Do something, perhaps using array[]
  if (found) {
    # Do something else only if we found SEARCH in the first file.
  }
}

答案 2 :(得分:0)

原件:

这是我认为我永远不会说的事情:

在这种情况下我会推荐grep,请在决定TLDR之前先听一听。

我建议这样做的唯一原因是grep将以布尔逻辑退出而awk不会。 (我有一个过时的awk版本,因为我在我的Mac上测试了这个,所以近年来这可能已经改变了。)

$ grep "zzz" test && echo true || false
$ awk "zzz" test && echo true || false
true
$ 

您可以设置一个简单的for循环来比较文件并写入(或者根据需要做一些事情)

$ for i in $(cat file1); do grep "$i" file2 || echo "$i" >> file2; done
grep: file2: No such file or directory
158
085
596
82
Worst012345678910Best
82
Worst012345678910Best
254
Worst012345678910Best
Worst012345678910Best
399

以上输出是重复的条目,第一行除外(显然)

$ cat file2
1
katyperry
KATY
PERRY
(@katyperry)
Followings
158
Followers
82
085
596
Rating
Worst012345678910Best
justinbieber
Justin
Bieber
(@justinbieber)
254
399
74
748
878
taylorswift13
Taylor
Swift
(@taylorswift13)
245
70
529
992

以下是测试中的Bash版本。

$ bash --version
GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin14)
Copyright (C) 2007 Free Software Foundation, Inc.
$   

编辑:

这方面的一个实际例子是编写一个脚本,无论脚本运行多少次都只编辑一次系统文件:

grep NOZEROCONF /etc/sysconfig/network 2> /dev/null || echo "NOZEROCONF=yes" >> /etc/sysconfig/network

在CentOS和RHEL系统上,上述行可以运行很多次,文件只能写一次。

可以做的另一件事是将一个命令的输出与另一个命令的输出进行比较,或者在这种情况下将grep用作逻辑开关:

for i in /dev/sd[^ab]*; 
do 
    ( pvs | grep -q "$i" ) && 
    echo "$i" configured || ( 
        code block to configure drive
done;