用awk处理多行变量,打印满足条件的未修改行
Processing multiline variable with awk, printing unmodified line meeting the condition
我有一个包含多行文件内容的变量。变量由大量命令(awk
、sed
、...)解析,这些命令充当变量的过滤器和 post 处理器。
echo "$variable" | awk1 | sed1 | awk2
问题不在于处理本身,而是我在处理过程中修改了行,失去了对变量原始值的跟踪。问题是最后的 awk
会根据结果、原始变量或不是 returns 进行条件检查。这就是我的问题所在。
我认为在 echo 之后用原始行创建这个变量是个好主意,但是我在以下子 shell 中继承它的任何尝试都失败了。
该解决方案必须是可移植的(符合 POSIX 标准)
变量格式:
John Smith - - [21/Mar/2017:09:24:33 +0100] Physics
Adam Miller - - [22/Feb/2019:09:24:33 +0100] Chemistry
我想将此文件中的日期与 YYYYMMDDHHMMSS
格式的给定日期(例如 20180101151515)进行比较,如果一行包含之后的日期,我想打印整行。
到目前为止我的代码:
date_after="19960101151515"
process=$(echo "$variable" |awk -F' - - ' '{print }' | sed "s/Jan/01/; s/Feb/02/;
s/Mar/03/; s/Apr/04/; s/May/05/; s/Jun/06/; s/Jul/07/;
s/Aug/08/; s/Sep/09/; s/Oct/10/; s/Nov/11/; s/Dec/12/" | awk -F'[/:\[ ]' -v date="$date_after" '{b=; if (b > date) {print [=12=]}}')
sed
、awk
、grep
、cut
的任意组合通常可以用单个 awk
代替。这还允许您存储原始数据并 return 它基于条件。
您可以很容易地看到以下 awk
进行了您感兴趣的转换(首先是 awk 和 sed)
awk '{ t=[=10=]
match(t,"\["); t=substr(t,RSTART+1)
match(t," ") ; t=substr(t,1,RSTART-1); split(t,a,"[/:]")
day=a[1]; year=a[3]; hhmmss=a[4]a[5]a[6];
month=sprintf("%02d",(match("JanFebMarAprMayJunJulAugSepOctNovDec",a[2])+2)/3)
print year month day hhmmss, t}'
所以现在您可以在 t
和 return 上插入您的条件,如果需要,原始 [=19=]
:
awk -v d="$date_after" '
{ t=[=11=]
match(t,"\["); t=substr(t,RSTART+1)
match(t," ") ; t=substr(t,1,RSTART-1); split(t,a,"[/:]")
day=a[1]; year=a[3]; hhmmss=a[4]a[5]a[6];
month=sprintf("%02d",(match("JanFebMarAprMayJunJulAugSepOctNovDec",a[2])+2)/3)
}
(t > d) { print [=11=] }'
基于:convert month from Aaa to xx in little script with awk
我有一个包含多行文件内容的变量。变量由大量命令(awk
、sed
、...)解析,这些命令充当变量的过滤器和 post 处理器。
echo "$variable" | awk1 | sed1 | awk2
问题不在于处理本身,而是我在处理过程中修改了行,失去了对变量原始值的跟踪。问题是最后的 awk
会根据结果、原始变量或不是 returns 进行条件检查。这就是我的问题所在。
我认为在 echo 之后用原始行创建这个变量是个好主意,但是我在以下子 shell 中继承它的任何尝试都失败了。 该解决方案必须是可移植的(符合 POSIX 标准)
变量格式:
John Smith - - [21/Mar/2017:09:24:33 +0100] Physics
Adam Miller - - [22/Feb/2019:09:24:33 +0100] Chemistry
我想将此文件中的日期与 YYYYMMDDHHMMSS
格式的给定日期(例如 20180101151515)进行比较,如果一行包含之后的日期,我想打印整行。
到目前为止我的代码:
date_after="19960101151515"
process=$(echo "$variable" |awk -F' - - ' '{print }' | sed "s/Jan/01/; s/Feb/02/;
s/Mar/03/; s/Apr/04/; s/May/05/; s/Jun/06/; s/Jul/07/;
s/Aug/08/; s/Sep/09/; s/Oct/10/; s/Nov/11/; s/Dec/12/" | awk -F'[/:\[ ]' -v date="$date_after" '{b=; if (b > date) {print [=12=]}}')
sed
、awk
、grep
、cut
的任意组合通常可以用单个 awk
代替。这还允许您存储原始数据并 return 它基于条件。
您可以很容易地看到以下 awk
进行了您感兴趣的转换(首先是 awk 和 sed)
awk '{ t=[=10=]
match(t,"\["); t=substr(t,RSTART+1)
match(t," ") ; t=substr(t,1,RSTART-1); split(t,a,"[/:]")
day=a[1]; year=a[3]; hhmmss=a[4]a[5]a[6];
month=sprintf("%02d",(match("JanFebMarAprMayJunJulAugSepOctNovDec",a[2])+2)/3)
print year month day hhmmss, t}'
所以现在您可以在 t
和 return 上插入您的条件,如果需要,原始 [=19=]
:
awk -v d="$date_after" '
{ t=[=11=]
match(t,"\["); t=substr(t,RSTART+1)
match(t," ") ; t=substr(t,1,RSTART-1); split(t,a,"[/:]")
day=a[1]; year=a[3]; hhmmss=a[4]a[5]a[6];
month=sprintf("%02d",(match("JanFebMarAprMayJunJulAugSepOctNovDec",a[2])+2)/3)
}
(t > d) { print [=11=] }'
基于:convert month from Aaa to xx in little script with awk