【问题标题】:replace CR LF in text file using `sed` or `fart` (Find And Replace Text)使用 `sed` 或 `fart` 替换文本文件中的 CR LF(查找和替换文本)
【发布时间】:2019-07-02 18:59:00
【问题描述】:

我有一个 1.5 GB 的 Windows 文本文件,其中一些行以 LF 结尾,大部分行以 CR+LF

结尾

你能帮忙解决一下sed脚本吗

  • 将所有 CR+LF 替换为 $|$
  • 将所有LF替换为CR+LF
  • 将所有 $|$ 替换为 CR+LF

我已尝试使用文本编辑器进行所有替换,但执行文件中的所有替换需要很长时间(1% 半小时)。我试过用fart替换它:

fart -c -B -b text.txt "\r\n" "$|$"

结果如下

replacement 0 occurence(s) in 0 file(s)..

【问题讨论】:

  • 我的错误,我尝试使用文本编辑器进行所有替换,但执行文件中的所有替换需要很长时间(1% 半小时)。我试过用 Fart (fart-it.sourceforge.net) fart -c text.txt "CRLF" "$|$" 替换它,但找不到任何东西可以替换
  • 除了 LF 之前的那些之外,文件中是否还有任何 CR?通常,当有一个 Windows 文件具有除 CR 之前的其他 LF 时,这些 LF 实际上并不表示一行的结尾。一个示例是从 Excel 导出的 CSV,其中beg,"foo\nbar",end\r\n 表示单行,其中一个单元格在引号内包含\n。那么您确定要将所有独立的 LF 视为代表行尾吗?
  • 该文件只是从数据库中提取的数据。大多数行都有正常的 CR+LF 结尾。但是有些内容因初始损坏的内容(附加 LF)而中断,它将正常的 CR+LF 转移到新行并将一行分成两行。任务是将提取的数据移回数据库,这就是出现问题的原因。如果没有额外的操作,初始行数和上传到数据库的行数将不匹配。

标签: windows text sed character-replacement


【解决方案1】:

一个带有 awk 的:

$ awk '{sub(/(^|[^\r])$/,"&\r")}1' file

测试它(0x0a 是 LF,0x0d 是 CR):

$ awk 'BEGIN{print "no\nyes\r\n\n\r"}' > foo
$ hexdump -C foo
00000000  6e 6f 0a 79 65 73 0d 0a  0a 0d 0a                 |no.yes.....|
0000000b
$ awk '{sub(/(^|[^\r])$/,"&\r")}1' foo > bar
$ hexdump -C bar
00000000  6e 6f 0d 0a 79 65 73 0d  0a 0d 0a 0d 0a           |no..yes......|
0000000d

【讨论】:

    【解决方案2】:

    我会这样做:首先删除行尾的所有\r,然后在行尾显式添加\r

    sed -e 's/\r$//' -e 's/$/\r/' file
    

    这是一个演示:

    $ printf "1\r\n2\n3\n4\r\n5\n" > file
    $ od -c file
    0000000   1  \r  \n   2  \n   3  \n   4  \r  \n   5  \n
    0000014
    $ sed -i -e 's/\r$//' -e 's/$/\r/' file
    $ od -c file
    0000000   1  \r  \n   2  \r  \n   3  \r  \n   4  \r  \n   5  \r  \n
    0000017
    

    这是 GNU sed。

    【讨论】:

      【解决方案3】:

      安装一个util like unix2dos 会更简单,它会自动完成。对于unix2dos,建议将CR+LF 转换为$|$ 的中间步骤(并返回)是不必要的。演示:

      # first dump a file with both *DOS* and *Unix* style line endings:
      hexdump -C <({ seq 2 | unix2dos ; seq 3 4; } )
      # the same file, run through unix2dos
      hexdump -C <({ seq 2 | unix2dos ; seq 3 4; } | unix2dos)
      

      输出:

      00000000  31 0d 0a 32 0d 0a 33 0a  34 0a                    |1..2..3.4.|
      0000000a
      00000000  31 0d 0a 32 0d 0a 33 0d  0a 34 0d 0a              |1..2..3..4..|
      0000000c
      

      或者更详细地说,一个前/后表,(有关格式的详细信息,请参阅man hexdump):

      hdf() { hexdump -v  -e '/1  "%_ad#  "' -e '/1 " _%_u\_\n"' $@ ; }
      # Note: the `printf` stuff keeps `paste` from misaligning the output.
      paste <(hdf <({ seq 2 | unix2dos ; seq 3 4; }) ; printf '\t\n\t\n' ; ) \
            <(hdf <({ seq 2 | unix2dos ; seq 3 4; } | unix2dos ))
      

      输出:

      0#   _1_    0#   _1_
      1#   _cr_   1#   _cr_
      2#   _lf_   2#   _lf_
      3#   _2_    3#   _2_
      4#   _cr_   4#   _cr_
      5#   _lf_   5#   _lf_
      6#   _3_    6#   _3_
      7#   _lf_   7#   _cr_
      8#   _4_    8#   _lf_
      9#   _lf_   9#   _4_
                  10#  _cr_
                  11#  _lf_
      

      【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-02-14
      • 1970-01-01
      • 2022-10-21
      • 2011-11-25
      • 1970-01-01
      • 2023-02-09
      • 1970-01-01
      • 2014-12-22
      相关资源
      最近更新 更多