在Windows 10环境中,我必须检查目录中有多少个CSV文件(分隔符为“;”)具有这种奇怪的换行模式:CR CR LF(如果愿意,可以使用\ r \ r \ n)。
但是,我无法将\r\r
与grep或awk都不匹配。在awk上,我还尝试将RS
更改为;
,将FS
更改为未使用的字符(#
),但显然awk匹配单个CR,而不是CR CR 。因此,在Windows中,awk会将CR CR LF视为CR LF和FNR输出的记录数量等于任何其他“正常端线”文件。
奇怪的是,使用Notepad ++,我可以清楚地看到CR CR LF(例如,在Excel中造成额外的换行符),并且使用内置的正则表达式查找器,搜索\r\r\n
与所有行匹配。是否可以在不删除某些CR的情况下强制awk对原始文本文件进行操作?
文件是这样的(我已经简化了一点):5行,其中4个字段用;
分隔,每行CRCRLF的结尾。用Notepad ++(和Excel)打开,我看到10行。
我希望以下GNU awk脚本返回16 5
BEGIN {RS = ";";FS = "#"; linecount = 0}
/\r\r/ {linecount = linecount + 1}
END {print FNR, linecount}
但是,它返回16 0
。如果我搜索匹配/\r/
,则获得16 5
。
因此,基本上,我担心Windows CMD Shell在将流传递给gawk之前会剥离两个连续CR中的一个(或者更好地说,是用LF替换CR LF对),我想知道是否是可以避免这种情况,因为我想使用gawk检测有多少文件具有此怪异的CR CR LF换行符。
我相信这里已经发布了一个非常类似的问题: In Perl, how to match two consecutive Carriage Returns?
答案 0 :(得分:1)
意识到存在重复(感谢@tripleee):
在MS-Windows下,gawk(和许多其他文本程序)在输入时将行
\r\n
转换为\n
,在输出时将行\n
转换为\r\n
。特殊的BINMODE
变量(例如)可以控制这些翻译,其解释如下:
- 如果
BINMODE
为“ r”或1,则在读取时设置为二进制模式(即读取时不进行翻译)。- 如果
BINMODE
是“ w”或两个,则在写入时设置二进制模式(即,写入时不转换)。- 如果
BINMODE
是“ rw”或“ wr”或3,则将二进制模式设置为读写模式。BINMODE=non-null-string
与BINMODE=3
相同(即,读或写均不翻译)。但是,如果字符串不是“ rw”或“ wr”之一,gawk会发出警告消息。来源:https://www.gnu.org/software/gawk/manual/gawk.html#PC-Using
要使awk保持其原始的POSIX风格,应使用BINMODE=3
。使用awk(或任何未修改的版本),通过检查记录是否以\r\r
结尾,您应该可以轻松地做到这一点。这是因为awk defaultly0使用RS="\n"
在记录中拆分了一个文件。当GOW使用GNU awk时,您有以下选择:
计数文件:
awk '/\r\r$/{f++; nextfile} END {print f,"files match"}' BINMODE=3 *.csv
计数文件并打印文件名:
awk '/\r\r$/{f++; print FILENAME; nextfile} END {print f,"files match"}' BINMODE=3 *.csv
计数文件,打印文件名和行数:
awk '(FNR==1){if (c) {print fname, c; f++}; c=0; fname=FILENAME}
/\r\r$/{c++}
END { print f,"files match" }' BINMODE=3 *.csv
注意:在任何POSIX系统上删除BINMODE=3
。
答案 1 :(得分:0)
您可以尝试使用GNU grep的-z
和-P
开关,请尝试以下操作:
grep -zcP "\r\r\n" *.csv | awk -F: "$2{c++}END{print c}"
所以我创建了一个像你这样说的文件:
awk 'BEGIN{ORS="\r\r\n"; OFS=";"; for(i=1;i<11;i++)print "aa","bb","cc",i>"strange.csv"}'
我可以像这样在csv文件中搜索\r\r\n
:
> grep -zcP "\r\r\n" *.csv
file1.csv:0
file2.csv:0
file3.csv:0
file_a.csv:0
file_b.csv:0
results.csv:0
strange.csv:1
并将其与awk
组合:
awk -F: "$2{c++}END{print c}"
获得计数:
> grep -zcP "\r\r\n" *.csv | awk -F: "$2{c++}END{print c}"
1
OR ,只需单独使用awk
:
> awk 'BEGIN{RS="";}/\r\r\n/{c++;nexfile}END{print c}' *.csv
1
因此,在以上grep
和awk
示例中,都应读取整个文件,而不是每回合都处理每一行。