Mau*_*zey 4 linux shell perl awk
我有一个管道|分隔文件.
文件:
106232145|"medicare"|"medicare,medicaid"|789
Run Code Online (Sandbox Code Playgroud)
我想计算每行中的字段数.我尝试了下面的代码
码:
awk -F '|' '{print NF-1}'
Run Code Online (Sandbox Code Playgroud)
这将结果返回为5而不是4.这是因为awk将"medicare | medicaid"作为两个不同的字段而不是一个字段
纯 Unix 解决方案(没有 awk/Perl):
$ cat /tmp/x1
1|2|3|34
4534|23442|1121|334434
$ head -1 /tmp/x1 | tr "|" "\012" | wc -l
4
Run Code Online (Sandbox Code Playgroud)
Perl 解决方案 - 1-liner:
$ perl5.8 -naF'\|' -e 'print scalar(@F)."\n";exit;' /tmp/x1
4
Run Code Online (Sandbox Code Playgroud)
但!!!!重要的!!!
这些解决方案中的每一个 - 以及其他答案中的那些 - 都不能 100% 工作!
也就是说,当它是一个真正的“管道分隔”文件时,它们都会中断,管道是字段中的有效字符(并且该字段被引用),真正的 CSV 文件的工作方式。
例如
$ cat /tmp/x2
"0|1"|2|3|34
4534|23442|1121|334434
$ perl5.8 -naF'\|' -e 'print scalar(@F)."\n";exit;' /tmp/x1
5 <----- BROKEN!!! There are only 4 fields, first field is "0|1"
Run Code Online (Sandbox Code Playgroud)
要解决这个问题,应该使用适当的 CSV(或分隔文件)解析器,例如 Perl 中的解析器:
$ perl5.8 -MText::CSV_XS
-ne '$csv=Text::CSV_XS->new({sep_char => "|"}); $csv->parse($_);
print $csv->fields(); print "\n"; exit;' /tmp/x2
Run Code Online (Sandbox Code Playgroud)
打印正确的值
4
Run Code Online (Sandbox Code Playgroud)
请注意,简单地使用复杂的 RegEx修复awkorsed解决方案并不容易,因为在包含管道和引用的 PSV 字段之上,规范还允许将引号作为字段的一部分。这不适合一个很好的 RegEx 解决方案。