我必须处理一个输入文件,如果它有超过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
答案 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