【问题标题】:How to replace New line and ^M chars with ~~ in Unix如何在 Unix 中用 ~~ 替换新行和 ^M 字符
【发布时间】:2013-12-07 03:59:51
【问题描述】:

我不擅长unix。

我有一个 csv 文件,其中包含多个列。其中,一列包含新行和^M 字符。我需要用~~ 替换两个“(这是单个单元格值)之间的所有它们,以便我可以将单元格值视为单个字段。这是示例文件:

"id","notes"
"N001","this is^M
test.

Again test

"
"N002","this is perfect"
"N00345","this is

having ^M
problem"

我需要这样的文件:

"id","notes"
"N001","this is~~test.~~~~Again test~~~~"
"N002","this is perfect"
"N00345","this is~~~~having ~~problem"

这样整个单元格的值可以作为单个字段值读取。

我需要在此要求中再添加一个案例,其中单元格中的数据包含"(双引号)。在这种情况下,我们可以识别结尾 " 后跟逗号。以下是更新的案例数据:

"id","notes"
"N001","this is^M
test. "Again test."

Again test

"
"N002","this is perfect"
"N00345","this is

having ^M
problem as it contains "
test"

我们可以保留" 或删除它。预期的输出是:

"id","notes"
"N001","this is~~test. "Again test."~~~~Again test~~~~"
"N002","this is perfect"
"N00345","this is ~~~~having ~~problem as it contains "~~test"

【问题讨论】:

    标签: file unix replace sed newline


    【解决方案1】:

    尝试使用sed

    sed -i -e 's/^M//g' -e '/"$/!{:a N; s/\n/~~/; /"$/b; ba}' file
    

    注意:要输入^M,请输入Ctrl+V,然后输入Ctrl+ M

    运行命令后的文件内容

    "id","notes"
    "N001","this is~~test.~~~~Again test~~~~"
    "N002","this is perfect"
    "N00345","this is~~~~having ~~problem"
    

    使用dos2unix,后跟sed

    dos2unix file
    sed -i '/"$/!{:a N; s/\n/~~/; /"$/b; ba}' file
    

    简短说明

    这里的想法是删除每行中不以"结尾的换行符

    sed -i '              # -i specifies in-place relace i.e. modifies file itself
      /"$/!{              # if a line doesn't contain end pattern, " at the end of a line, then do following
        :a                # label 'a' for branching/looping
          N;              # append the next line of input into the pattern space 
          s/\n/~~/;       # replace newline character '\n' with '~~' i.e. suppress new lines
          /"$/b;          # if a line contains end pattern then branch out i.e. break the loop
          ba              # branch to label 'a' i.e. this will create loop around label 'a'
      }                   
    ' file                # input file name
    

    详情请咨询man sed


    编辑

    有时单元格中的数据本身包含 "。

    使用sed

    sed -i ':a N; s/\n/~~/; $s/"~~"/"\n"/g; ba' file
    

    运行命令更新案例数据后的文件内容

    "id","notes"
    "N001","this is~~test. "Again test."~~~~Again test~~~~"
    "N002","this is perfect"
    "N00345","this is~~~~having ~~problem as it contains "~~test"
    

    使用perl单行

    perl -0777 -i -pe 's/\n/~~/g; s/"~~("|$)/"\n$1/g;' file
    

    【讨论】:

    • 嗨,我猜你的 sed 命令很完美。但它会在控制台评估器上打印输出,而不是将其保存在同一个文件中。我要使用 -i 选项吗?请回复。非常感谢。
    • @user3021141 是的,您需要使用-i 选项进行就地替换。更新了我的答案。
    • jkshah,你是 unix 大师。非常感谢。但是还有一个问题,当我运行单个 sed 命令时,我看到文件中的 ^M 尚未替换。
    • @user3021141 不客气,没什么,我还在学习。这可能是因为您可能确实输入了^M,您是否输入了Ctrl+VCtrl+M?如果这变得麻烦,我会推荐dos2unix 选项
    • 不,我尝试按照您指定的方式打印 ^M。不用担心,我会尝试第二种选择。无论如何,你是优秀的Gujju。谢谢。
    【解决方案2】:

    您可以使用sed 命令完成此操作

    单独替换 '^M'

    sed -i 's|^M|~~|g' file_name
    

    编辑: 感谢您的评论。

    添加语句替换'^M and new line'

    替换'^M 和换行'**

    sed -i ':a;N;$!ba;s|^M\n|~~|g' file_name
    

    要在控制台中获取“^M”,您应该同时按Cntrl+v+m

    【讨论】:

    • 在引号之间仍然需要 ~~ for \n
    【解决方案3】:

    使用tr

    $ tr '<Ctrl>+m' '~'
    

    【讨论】:

      【解决方案4】:
      sed 's/\^M/~~/;t nextline
      b
      : nextline
      N
      s/\n/~~/
      s/^[^"]*\("[^"]*"\}\{1,\}[^"]*$
      t
      b nextline
      "
      

      不仅要更改 ^M,还要更改引号之间的新行。

      ^M 在 unix 会话中使用 CTRL+V 后跟键盘上的 CTRL+M 获得

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-06-08
        • 2023-04-05
        • 2010-09-14
        • 2012-11-28
        • 1970-01-01
        • 2016-08-15
        • 1970-01-01
        相关资源
        最近更新 更多