使用' awk'在CLI上对文件内容进行预检查并执行操作

时间:2017-06-02 20:54:20

标签: text awk text-processing

我必须处理一个输入文件,如果它有超过1条记录(基本上是除标题之外的任何行) 解析第1列和第3列,看它是否有字符串"测试"并排除那些行 然后,将输出写入 - 最好再次写入同一文件。

我搜索了SE和Google,并将其视为非常接近的选项:Using `awk` to print number of lines in file in the BEGIN section 以及Ed Morton在同一主题上的评论。

我有部分工作,但需要把所有东西放在一起。

用于测试设置我在输入文件中创建了15行。

$awk 'NR==FNR {next} FNR==1 {x=NR-1} { print x}'  {filename.csv,filename.csv}
15
15
15
15
15
15
15
15
15
15
15
15
15
15
15

验证x能够保存行数。

我希望,下面会处理我的输入文件中的所有15行,因为x保持15 - 但它似乎只是处理一行。

$awk 'NR==FNR {next} FNR==1 {x=NR-1} { if(x>1){print x;exit 0;}}'  {filename.csv,filename.csv}
15

这是输入文件结构和预期输出。

before the process 

filename.csv
col1,col2,col3,.....coln
test,xxx,test,.....
test,xxx,xxx,.....
xxx,xxx,test,.....
yyy,yyy,yyy,.....
zzz,zzz,zzz,.....

after the process

filename.csv
col1,col2,col3,.....coln
yyy,yyy,yyy,.....
zzz,zzz,zzz,.....

此部分用于检查column1和column3

if ($1 !~ /[Tt][Ee][Ss][Tt]/ && $3 !~ /[Tt][Ee][Ss][Tt]/) {print $0} else exit 0}

P.S。
-1文件至少包含标题记录 -2 getline不可用
-3无法从moreutils安装海绵重定向到同一文件 -4计划使用tee重定向到同一文件。

all of the code | tee filename.csv

1 个答案:

答案 0 :(得分:0)

从您的第一段和示例输入/输出中,如果您想要完整的字符串匹配,这听起来就是您所需的全部内容:

$ awk -F, '(NR==1) || ((tolower($1) != "test") && (tolower($3) != "test"))' file.csv
col1,col2,col3,.....coln
yyy,yyy,yyy,.....
zzz,zzz,zzz,.....

如果你想要一个部分字符串匹配,那么它将是:

awk -F, '(NR==1) || (!index(tolower($1),"test") && !index(tolower($3),"test"))' file.csv

如果你想要部分正则表达式匹配:

awk -F, '(NR==1) || ((tolower($1) !~ /test/) && (tolower($3) !~ /test/))' file.csv

最后如果你想要一个完整的正则表达式匹配:

awk -F, '(NR==1) || ((tolower($1) !~ /^test$/) && (tolower($3) !~ /^test$/))' file.csv

对不起,我不明白您发布的脚本或其他文本的意图。我想你可能对awk的运作方式有严重的误解。获得由Arnold Robbins撰写的Effective Awk Programming,第4版。

如果你有GNU awk那么修改输入文件是:

awk -i inplace -F, '...' file.csv

和任何awk:

awk -F, '...' file.csv > tmp && mv tmp file.csv

不要尝试将输出重定向到输入文件(包括通过管道中的其他命令),因为shell可能会打开该文件以准备输出,然后再将其作为输入读取。

鉴于您的新要求仅在匹配时修改输入文件,请执行以下操作:

awk -F, '
    NR==1 {hdr=$0 ORS}
    ...$1/3 test... {printf "%s", hdr; hdr=""; print}
    END {exit (hdr=="" ? 0 : 1)}
' file.csv > tmp && mv tmp file.csv; rm -f tmp