在字段中循环并在awk中打印上一行
我一直在与awk斗争,以使这项工作,但我一直无法做到这一点。我有以下两行:在字段中循环并在awk中打印上一行,awk,Awk,我一直在与awk斗争,以使这项工作,但我一直无法做到这一点。我有以下两行: = filename: /path/to/file years="1990,2001" 我需要每年根据给定值检查引号之间的距离,然后打印前一行(如果匹配),并获取文件名,结果只需要匹配找到的第一行。值和运算符,即=、、~将通过变量传递给awk,如: value="2000" string"=\$2 < $value" # just an exa
= filename: /path/to/file
years="1990,2001"
我需要每年根据给定值检查引号之间的距离,然后打印前一行(如果匹配),并获取文件名,结果只需要匹配找到的第一行。值和运算符,即=、、~将通过变量传递给awk,如:
value="2000"
string"=\$2 < $value" # just an example
awk ... '"$string"' ...
输出匹配:
/mnt/project1/record2.txt
/mnt/project1/record4.txt
我还在学习AWK,但你想要类似的东西吗 下面是script.awk: 使用以下输入运行: 就像这样:
$ ./script.awk input
filename: /path/to/file5
试着做一些超出你展示的假设。。。。 下面是一个如何解析它的示例
$: cat tst
= filename: /path/to/file/none
years="1890,1001"
= filename: /path/to/file/first
years="1990,0001"
= filename: /path/to/file/none
years="1890,1001"
= filename: /path/to/file/both
years="1990,2001"
= filename: /path/to/file/none
years="1890,1001"
= filename: /path/to/file/second
years="1790,2001"
= filename: /path/to/file/none
years="1890,1001"
$: awk '/filename:/ { fn=$3 } /years=/{ split($0,a,"[^0-9]+");
for (y in a) { if (a[y]>1950) { printf "%s(%s)\n",fn,a[y]; break; } } }' tst
/path/to/file/first(1990)
/path/to/file/both(1990)
/path/to/file/second(2001)
如果你需要这些年的变量,你可以这样做
awk -v y0=1990 -v y1=2001 '
$0 ~ "^years=\"" y0 "," y1 "\"$" {
printf("filename: %s\n", filename);
}
/^= filename/ {
filename = $3
}
' file.txt
假设:
OP将始终搜索小于的日期。请将样本输入无描述、无图像、无链接和该样本输入的所需输出添加到您的问题中,无评论。您的示例显示年份<2000;您是否总是在寻找一个小于,=,date1的日期?否,它需要是任何运算符或~如果需要的话,也可以是字符串。“$2[operator][value]”将作为字符串传递给AWK:即var=\$2<$search\u值,然后是AWK…'$var'…@bcHelix这是一个与您的问题中当前显示的要求非常不同的要求,您可以从迄今为止收到的答案中看到这一点。请您的问题提供更清晰的需求说明和更真实的示例。您的示例代码显示了一个大于1950年的测试,但示例输入/输出基于一个小于2000年的测试;可能应该考虑更新问题,以便对你正在做的事情提供更简洁/清晰的解释;提供两个不同的例子不会有什么坏处,例如,>1950,@markp fuso:当然,OP在我发布我的答案后编辑了他们的问题……请查看何时/如何调用getline。@EdMorton:我的代码到底出了什么问题?请阅读那篇文章,它会告诉你的。我写这篇文章是为了不必反复讨论这些问题。这篇文章看起来很有效。这可以与字符串一起使用;i、 a[y]~一些字符串引用字符串-a[y]~一些字符串。
$ ./script.awk input
filename: /path/to/file5
$: cat tst
= filename: /path/to/file/none
years="1890,1001"
= filename: /path/to/file/first
years="1990,0001"
= filename: /path/to/file/none
years="1890,1001"
= filename: /path/to/file/both
years="1990,2001"
= filename: /path/to/file/none
years="1890,1001"
= filename: /path/to/file/second
years="1790,2001"
= filename: /path/to/file/none
years="1890,1001"
$: awk '/filename:/ { fn=$3 } /years=/{ split($0,a,"[^0-9]+");
for (y in a) { if (a[y]>1950) { printf "%s(%s)\n",fn,a[y]; break; } } }' tst
/path/to/file/first(1990)
/path/to/file/both(1990)
/path/to/file/second(2001)
awk -v y0=1990 -v y1=2001 '
$0 ~ "^years=\"" y0 "," y1 "\"$" {
printf("filename: %s\n", filename);
}
/^= filename/ {
filename = $3
}
' file.txt
$ cat file_year.dat
= filename: /mnt/project1/record1.txt
years="2005,2019,2011,2012,2013" # no match
= filename: /mnt/project1/record2.txt
years="1996,2000" # match on 1996 < 2000
= filename: /mnt/project1/record3.txt
years="2005,2001,2012" # no match
= filename: /mnt/project1/record4.txt
years="2010,2009,1997,2000" # match on 1997 < 2000
= filename: /mnt/project1/record5.txt
years="2010,2009,2007,1947" # match on 1947 < 2000
awk -v tgt=2000 ' # pass target date in as awk variable "tgt"
/^= filename: / { fn=$(NF) # save the filename in awk variable "fn"
next # skip to the next line of input
}
fn != "" { n=split($0,arr,"[,\"]") # if "fn" is set then split the current line on double quotes
# and commas; store results (ie, individual years)
# in array "arr[]"
for (i=2; i<n; i++) # process arr[2-(n-1)] elements (individual years)
if ( arr[i] < tgt ) # if less than "tgt" ...
{ print fn # print associated filename ("fn") and ...
break # break out of loop
}
fn="" # clear "fn" varible
}
' file_year.dat
/mnt/project1/record2.txt
/mnt/project1/record4.txt
/mnt/project1/record5.txt