【问题标题】:How do you search for files containing DOS line endings (CRLF) with grep on Linux?如何在 Linux 上使用 grep 搜索包含 DOS 行尾 (CRLF) 的文件?
【发布时间】:2010-09-09 14:02:36
【问题描述】:

我想在 Linux 上使用 grep 搜索包含 DOS 行结尾的文件。像这样的:

grep -IUr --color '\r\n' .

以上内容似乎与文字 rn 匹配,这不是我们想要的。

this 的输出将通过 xargs 传递到 todos 中,像这样将 crlf 转换为 lf

grep -IUrl --color '^M' . | xargs -ifile fromdos 'file'

【问题讨论】:

  • 你试过dos2unix吗?它会自动修复行尾。
  • 我不太确定,但 iirc 在 ' 和 " 中引用模式是有区别的。在 ' 中包含的模式中的 Afaik 转义序列被解释为正确的字符串,因此 '\r' 将是等效的到 "\\r" 和 "\r" 与 '. 没有等价物(至少在该符号中)
  • Anticom:在这种情况下,您是正确的,' 和 " 之间的区别无关紧要;但是,通常它们是不同的,因为 ' 包围的字符串是弱引用的,而 " 是强引用的。我利用的最大优势是 $ 扩展或 `` 不要在弱引用字符串中扩展。请参阅bash-hackers on quoting 了解更多信息。
  • 最简单的方法是使用现代dos2unix-ic 开关。对于 LF 文件,您可以使用 unix2dos-ic 进行搜索。它不会修改文件。仅报告。
  • 因为这是有关 Linux 上 Windows 行尾/回车的任何问题的最佳答案,我认为值得注意的是,您可以在终端中使用命令查看它们cat -v somefile.txt;他们显示为^M

标签: linux bash grep newline


【解决方案1】:

使用 Ctrl+VCtrl+M 在 grep 字符串中输入文字回车符.所以:

grep -IUr --color "^M"

会起作用 - 如果 ^M 有一个文字 CR,你按照我的建议输入。

如果您想要文件列表,还需要添加-l 选项。

说明

  • -I忽略二进制文件
  • -U 防止 grep 删除 CR 字符。默认情况下,如果它确定它是一个文本文件,它就会这样做。
  • -r递归读取每个目录下的所有文件。

【讨论】:

  • 作为一种可行的快速破解方法,但我认为人类 readbale 解决方案将是:grep $'\r' /bash shell only/ 或 grep printf '\r'
  • @akostadinov +1,但是反引号被您的评论解释了;)换句话说,第二个选项是 grep $(printf '\r')。但对于涉及 bash 的大多数实际用途,我会坚持使用 $'\r'
  • 注意:-U 选项仅与 Windows(或 cygwin)相关,但在那里很关键。在 Windows 上,如果没有它,该命令将无法运行。
  • -I 选项的意义何在?根据手册,在我看来二进制文件被认为是不匹配的。 -I-U(强制二进制类型)的组合不应该导致所有文件都被视为不匹配吗?
  • 您提到 '-l' 标志作为附加选项,但我认为它应该包含在主要答案中,因为该问题本质上要求提供文件列表。此外,它还可以加快搜索速度。
【解决方案2】:

grep 可能不是您想要的工具。它将为每个文件中的每个匹配行打印一行。除非你想在一个 10 行的文件上运行 10 次 todos,否则 grep 并不是最好的方法。使用 find 在树中的每个文件上运行文件,然后对“CRLF”进行 grepping,将为每个具有 dos 样式行结尾的文件提供一行输出:

find . -not -type d -exec file "{}" ";" | grep CRLF

会给你类似的东西:

./1/dos1.txt: ASCII text, with CRLF line terminators
./2/dos2.txt: ASCII text, with CRLF line terminators
./dos.txt: ASCII text, with CRLF line terminators

【讨论】:

  • 我已经破解了这个,但还是谢谢你。 grep -IUrl --color '^M' . | xargs -ifile fromdos 'file'
  • grep 的 -l 选项告诉它只列出文件(一次)而不是列出每个文件中的匹配项。
  • 不是一个好的解决方案,依赖于file 程序的(未记录的,面向人类消费的)行为。这是非常脆弱的。对于(仅一个)示例:它不适用于 XML 文件,file 报告 XML document text 无论换行符类型如何。
  • @leonbloy,我的find (GNU findutils) 4.4.2(Ubuntu 12.04)上的选项似乎是小写的-m /dev/null
  • 我最喜欢这个答案。我只是做了find . -type f | xargs file | grep CRLF
【解决方案3】:

如果你的 grep 版本支持 -P (--perl-regexp) 选项,那么

grep -lUP '\r$'

可以使用。

【讨论】:

  • 这很慢...
【解决方案4】:
# list files containing dos line endings (CRLF)

cr="$(printf "\r")"    # alternative to ctrl-V ctrl-M

grep -Ilsr "${cr}$" . 

grep -Ilsr $'\r$' .   # yet another & even shorter alternative

【讨论】:

    【解决方案5】:

    查询是搜索...我有类似的问题...有人提交了混合行 结束到版本控制,所以现在我们有一堆文件0x0d 0x0d 0x0a 行尾。请注意

    grep -P '\x0d\x0a'
    

    找到所有行,而

    grep -P '\x0d\x0d\x0a'
    

    grep -P '\x0d\x0d'
    

    没有发现任何行,因此 grep 中可能存在“其他”内容 说到行尾模式……对我来说很不幸!

    【讨论】:

      【解决方案6】:

      如果像我一样,您的极简主义 unix 不包含 file 命令之类的细节,并且您的 grep 表达式中的反斜杠不配合,试试这个:

      $ for file in `find . -type f` ; do
      > dump $file | cut -c9-50 | egrep -m1 -q ' 0d| 0d'
      > if [ $? -eq 0 ] ; then echo $file ; fi
      > done
      

      您可能希望对上述内容进行的修改包括:

      • 调整 find 命令以仅定位您要扫描的文件
      • dump 命令更改为 od 或您拥有的任何文件转储实用程序
      • 确认 cut 命令包括前导空格和尾随空格,以及 dump 实用程序输出的十六进制字符
      • dump 输出限制为前 1000 个字符左右以提高效率

      例如,使用 od 而不是 dump 可能适合您:

       od -t x2 -N 1000 $file | cut -c8- | egrep -m1 -q ' 0d| 0d|0d$'
      

      【讨论】:

        【解决方案7】:

        使用 RipGrep(取决于您的 shell,您可能需要引用最后一个参数):

        rg -l \r
        
        -l, --files-with-matches
        Only print the paths with at least one match.
        

        https://github.com/BurntSushi/ripgrep

        【讨论】:

        • 这似乎没有给出正确的答案,它给了我所有的文件
        【解决方案8】:

        你可以在 unix 中使用 file 命令。它为您提供文件的字符编码以及行终止符。

        $ file myfile
        myfile: ISO-8859 text, with CRLF line terminators
        $ file myfile | grep -ow CRLF
        CRLF  
        

        【讨论】:

          【解决方案9】:

          dos2unix 有一个文件信息选项,可用于显示要转换的文件:

          dos2unix -ic /path/to/file
          

          要递归地执行此操作,您可以使用bashglobstar 选项,对于当前的shell,该选项是通过shopt -s globstar 启用的:

          dos2unix -ic **      # all files recursively
          dos2unix -ic **/file # files called “file” recursively
          

          您也可以使用find

          find -type f -exec dos2unix -ic {} +            # all files recursively (ignoring directories)
          find -name file -exec dos2unix -ic {} + # files called “file” recursively
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2011-02-08
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2019-01-10
            • 2018-05-06
            • 2014-01-29
            相关资源
            最近更新 更多