[英]Find nth row using AWK and assign them to a variable
好的,我有两个文件:一个是基线,另一个是生成的报告。 我必须验证两个文件中匹配的特定字符串,这不仅仅是一个单词,请参见下面的示例:
.
.
name os ksd
56633223223
some text..................
some text..................
我在这里的搜索标准是找到唯一的数字,例如“ 56633223223”,并在1行以上和3行以下进行检索,我可以在基本文件和报表上进行查找,然后比较它们是否匹配。 总体而言,我为此需要shell脚本。
由于上方和下方的字符串是唯一的,但是行数却有所不同,因此我将其放在名为“ actlist”的文件中:
56633223223 1 5
56633223224 1 6
56633223225 1 3
.
.
现在,从“ Rcount”下面,我可以获得要执行的迭代次数,在每次迭代中,我都必须获得第ith行,并查看单词数是否为3,如果是,则将这些值转换为变量形式并使用类似的内容
我被困在下面,要使用哪个命令。 我正在考虑使用AWK,但如果有更好的建议,请指教。 这是一些伪代码,显示我要执行的操作:
xxxxx=/root/xxx/xxxxxxx
Rcount=`wc -l $xxxxx | awk -F " " '{print $1}'`
i=1
while ((i <= Rcount))
do
record=_________________'(Awk command to retrieve ith(1st) record (of $xxxx),
wcount=_________________'(Awk command to count the number of words in $record)
(( i=i+1 ))
done
注意:记录,计数值稍后会打印到日志文件中。
听起来您正在寻找这样的东西:
#!/bin/bash
while read -r word1 word2 word3 junk; do
if [[ -n "$word1" && -n "$word2" && -n "$word3" && -z "$junk" ]]; then
echo "all good"
else
echo "error"
fi
done < /root/shravan/actlist
这将遍历输入文件的每一行,将三列分配给word1
, word2
和word3
。 read
的-n
测试尚未为每个变量分配空值。 -z
检查只有三列,因此$junk
为空。
我保证你这一切都是错的。 在file1中查找单词并在file2和file3中搜索这些单词仅是:
awk '
NR==FNR{ for (i=1;i<=NF;i++) words[$i]; next }
{ for (word in words) if ($0 ~ word) print FILENAME, word }
' file1 file2 file3
或类似的东西(假设一个简单的grep -f file1 file2 file3
是不够的)。 它不涉及shell循环来调用awk来拉出字符串以保存在shell变量中以传递给其他shell命令等。
到目前为止,您正在做的只是要求我们帮助您实现部分您认为是解决问题的方案,但是我们正在努力做到这一点,因为您的要求与任何问题都不相关对于听起来像是您的问题的一种合理的解决方案,因此很难提出任何明智的建议。
如果您通过整个过程的示例输入和预期输出来告诉您您正在尝试做什么,那么我们可以为您提供帮助。
我们似乎什么都没有,所以让我们尝试一下我认为您可能想要的解决方案,然后再从中获取。
并排查看这两个文件“旧”和“新”( cat -n
添加的行号):
$ paste old new | cat -n
1 a b
2 b 56633223223
3 56633223223 c
4 c d
5 d h
6 e 56633223225
7 f i
8 g Z
9 h k
10 56633223225 l
11 i
12 j
13 k
14 l
现在让我们看一下这个“ actlist”:
$ cat actlist
56633223223 1 2
56633223225 1 3
并在上述所有3个文件上运行该awk命令(是的,我知道它可能更简短,更高效等,但目前偏爱简单明了):
$ cat tst.awk
ARGIND==1 {
numPre[$1] = $2
numSuc[$1] = $3
}
ARGIND==2 {
oldLine[FNR] = $0
if ($0 in numPre) {
oldHitFnr[$0] = FNR
}
}
ARGIND==3 {
newLine[FNR] = $0
if ($0 in numPre) {
newHitFnr[$0] = FNR
}
}
END {
for (str in numPre) {
if ( str in oldHitFnr ) {
if ( str in newHitFnr ) {
for (i=-numPre[str]; i<=numSuc[str]; i++) {
oldFnr = oldHitFnr[str] + i
newFnr = newHitFnr[str] + i
if (oldLine[oldFnr] != newLine[newFnr]) {
print str, "mismatch at old line", oldFnr, "new line", newFnr
print "\t" oldLine[oldFnr], "vs", newLine[newFnr]
}
}
}
else {
print str, "is present in old file but not new file"
}
}
else if (str in newHitFnr) {
print str, "is present in new file but not old file"
}
}
}
。
$ awk -f tst.awk actlist old new
56633223225 mismatch at old line 12 new line 8
j vs Z
之所以输出该结果,是因为56633223225之后的第二行在“旧”文件中为j
,但是在文件“新”中的Z
和文件“ actlist”中说这2个文件必须从该模式之前的一行到该行之后的3行是公共的。
那是你想做的吗? 上面的代码对ARGIND使用GNU awk,但是对于其他awk来说,解决方法很简单。
使用以下代码:
awk '{if (NF == 3) { word1=$1; word2=$2; word3=$3; print "Words are:" word1, word2, word3} else {print "Line", NR, "is having", NF, "Words" }}' filename.txt
我已经根据要求给出了解决方案。
awk '{ # awk starts from here and read a file line by line
if (NF == 3) # It will check if current line is having 3 fields. NF represents number of fields in current line
{ word1=$1; # If current line is having exact 3 fields then 1st field will be assigned to word1 variable
word2=$2; # 2nd field will be assigned to word2 variable
word3=$3; # 3rd field will be assigned to word3 variable
print word1, word2, word3} # It will print all 3 fields
}' filename.txt >> output.txt # THese 3 fields will be redirected to a file which can be used for further processing.
这是按照要求进行的,但是还有许多其他方法可以执行此操作,但是有人要求使用awk。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.