【问题标题】:Using sed or VIM to replace space with new line使用 sed 或 vim 用新行替换空格
【发布时间】:2013-12-28 21:42:28
【问题描述】:

我有以下数据。

1455931_at Chrna3 1420468_at Asb17 1445520_at −−− 1436717_x_at Hbb−y 1431788_at Fabp12 1458975_at −−−

使用sed 或VIM 编辑器如何将其更改为

1455931_at Chrna3 
1420468_at Asb17 
1445520_at −−− 
1436717_x_at Hbb−y 
1431788_at Fabp12 
1458975_at −−−

所以所有包含_at 的单词将是每行的第一个。 每行由成对的 _at 和基因术语组成。

【问题讨论】:

    标签: linux unix sed vi


    【解决方案1】:

    在 Vim 中,我会这样做:

    :%s/ /^M/g
    :g/_at/j
    

    ^M 的输入方式是按 control-V(Windows 上为 control-Q),然后按 Enter/Return 键。

    这假定标记之间有单个空格;正如@Floris 建议的那样,您可以使用s/ \+/^M/g 将多个连续空格转换为一个换行符。或者您可以使用 s/\v\s+/^M/g 对任何连续的空格(包括制表符以及文字空格字符)执行相同的操作。

    【讨论】:

    • 只要有一个空格就可以了。也许想要%s/ \+/^M/g 作为第一个命令?它会处理额外的空白。
    【解决方案2】:

    惊人但真实:

    sed 's/\([^ ]*\) \(.[^ ]* \)/\1 \2\
    > /g' <<<"1455931_at Chrna3 1420468_at Asb17 1445520_at −−− 1436717_x_at Hbb−y 1431788_at Fabp12 1458975_at −−−"
    1455931_at Chrna3 
    1420468_at Asb17 
    1445520_at −−− 
    1436717_x_at Hbb−y 
    1431788_at Fabp12 
    1458975_at −−−
    

    换句话说,我使用的sed 字符串中有一个物理回车符(&gt; 是控制台添加的):

    sed 's/\([^ ]*\) \(.[^ ]* \)/\1 \2\
    > /g'
    

    您可以尝试使用其他表达式(现在我假设平衡对,但如果您特别想匹配第一个字符串末尾的at,您可以)。

    【讨论】:

    • 是否可以在 VIM 中使用它?我在 VIM 可视模式下尝试过,但失败了 :'&lt;,'&gt;!sed sed 's/\([^ ]*\) \(.[^ ]* \)/\1 \2\ ENTER,但在添加 /g' 之前失败了
    • 在 bash 或其他 POSIX shell 中,您还可以利用 POSIX 字符串并将其键入为 $'...\\\n/g'
    • @MarkReed - 换行的三个反斜杠?你可以解释吗?请问?
    • @Floris - $'\\\n' 被外壳程序转换为与您的答案相同的序列:反斜杠后跟换行符; sed 无法区分。在 POSIX 字符串 $'...' 中,\\ 变为文字反斜杠,\n 变为换行符,因此将它们放在一起您将得到 \\\n 用于反斜杠 + 换行符。
    【解决方案3】:

    使用 sed:s/ /\n/g; s/_at\n/_at /g 可能有一个更优雅的解决方案,但这个解决方案可以。

    【讨论】:

    • 看起来很优雅,但在我的sed (Mac OS) 版本中,\n 无法识别。
    【解决方案4】:

    对于你的例子,

    sed -e 's/\(_at [0-9a-zA-Z−]*\) /\1\n/g'
    

    【讨论】:

      【解决方案5】:
      sed 's/\(_at[[:blank:]]\{1,\}[^[:blank:]\{1,\}\)\([[:blank:]]\)/\1\
      \2/g' YourFile
      

      这允许任何“空格”作为分隔符,并且在一次或多次出现时,最后一行没有 \n。这需要在以_at 终止的字符串的任何部分之后使用 1 个“单词”,而不是单词的交替(我这边的解释)。

      这并不能避免将 2 个“_at”写在 2 个单独的行上(如果有一个缺失/空字)

      【讨论】:

        【解决方案6】:

        这是一个awk 解决方案:

        awk '{for (i=1;i<=NF;i+=2) print $i,$(i+1)}' file
        1455931_at Chrna3
        1420468_at Asb17
        1445520_at ...
        1436717_x_at Hbb.y
        1431788_at Fabp12
        1458975_at ...
        

        这会打印两个和两个字段。

        另一个版本:

        awk '{printf $0 FS;getline;print}' RS=" " file
        

        【讨论】:

          【解决方案7】:

          您可以使用它来查找第一个单词以“_at”结尾的所有 2 单词对

          grep -oP '\S+_at\s+\S+' file
          

          或者,在每第二个单词后换行:

          tr -s '[:blank:]' '\n' < file | paste -d " " - -
          

          【讨论】:

            猜你喜欢
            • 2021-07-12
            • 1970-01-01
            • 1970-01-01
            • 2018-05-24
            • 2018-03-22
            • 2012-03-02
            • 1970-01-01
            • 1970-01-01
            • 2014-11-27
            相关资源
            最近更新 更多