【问题标题】:Insert newline before/after match for TSV在 TSV 匹配之前/之后插入换行符
【发布时间】:2018-07-14 02:55:08
【问题描述】:

我想弄清楚如何完成一些正则表达式匹配以插入新行。下面的示例输入/输出...

TSV 数据示例:

Name    Monitoring  Tags
i-RBwPyvq8wPbUhn495 enabled "some:tags:with:colons=some:value:with:colons-and-dashes/and/slashes/yay606-values-001  some:other:tag:with-colons-and-hypens=MACHINE NAME  Name=NAMETAG    backup=true"
i-sMEwh2MXj3q47yWWP enabled "description=RANDOM BUSINESS INT01  backup=true Name=SOMENAME"

期望的输出:

Name    Monitoring  Tags
i-RBwPyvq8wPbUhn495 enabled "some:tags:with:colons=some:value:with:colons-and-dashes/and/slashes/yay606-values-001
some:other:tag:with-colons-and-hyphens=MACHINE NAME 
Name=NAMETAG    
backup=true"
i-sMEwh2MXj3q47yWWP enabled "description=RANDOM BUSINESS INT01  
backup=true 
Name=SOMENAME"

我可以保证这些引号中的每个 key=value 都由硬/文字选项卡分隔,尽管 StackOverflow 代码块在 HTML 中的显示方式可能不是这样,它们确实转移到代码块编辑器中,数据在Tags 列下方是引号,因此即使它们是制表符分隔的,它们也会保留在Tags 列中。无论出于何种原因,我都无法成功获得预期的结果。

在我微不足道的尝试中,我基本上捕获了 "" 之间的所有内容,就好像在我的正则表达式搜索中标签没有分开,因为我使用了通配符 [TAB].*=.*[TAB] 显然不起作用,因为那样我就输了每行的第一次/最后一次出现之间的所有内容。我尝试将它们存储在捕获组中,但没有成功。

我正在寻找一个 unix 工具集解决方案(sed、awk、perl 等)。感谢任何/所有帮助!

【问题讨论】:

  • 用你的字符串测试过,看起来这样可以工作:sed -re 's/\t+/\n/g' test.txt
  • @LuisMuñoz 将为所有选项卡/列添加新行,我只想要标签列中的新行。我测试了您提供的内容,尽管它确实接近(在标签列中的每个选项卡之前添加了新行),但它也破坏了其余数据。
  • 您只是想在双引号内用换行符替换制表符吗?
  • @EdMorton 我认为这是一个安全的方案,是的。

标签: regex bash perl awk sed


【解决方案1】:

这可能对你有用(GNU sed):

sed 's/\S\+=\S\+/\n&/2g' file

在第二个或更多包含= 的非空字符串之前插入换行符。

【讨论】:

    【解决方案2】:

    这基本上是 ctac_ 的 awk 答案转换为 perl:

    perl -pe'1 while s/(".*)\t(.*")/$1\n$2/s' file.tsv
    

    \t 可能会被 \t\s* 替换,如果您只想在每个 tab-and-then-some 中添加一个换行符。

    【讨论】:

      【解决方案3】:

      你可以试试这个 sed (GNU sed) 4.4

      sed -E ':A;s/(".*)\t(.*")/\1\n\2/;tA' TSV_Data_File
      

      使用 OSX sed,你可以试试这个。 我认为 \t 没问题。

      sed -E '
      :A
      s/(".*)\t(.*")/\1\
      \2/
      tA
      ' TSV_Data_File
      

      简要说明:

      捕捉"里面的文字

      用\n替换最后一个\t

      如果发生替换,则跳转到 A,否则继续

      使用 awk :

      awk -v RS='"' 'NR%2==0{gsub("\t","\n")}1' ORS='"' TSV_Data_File

      【讨论】:

      • 太棒了,它确实有效!你能分解并描述一下这个表达吗?好奇它是如何在多个匹配中工作的,即使您显然只使用两个捕获组?
      • 另外,我很好奇是否有人可以使用 OSX sed 进行这项工作,这在 GNU sed 上可以正常工作,但如果它可以更便携,那就太好了。
      • 这是我认为的便携版:sed -e ':A;s/\("[^\t]*\)\t\(.*"\)/\1\n\2/;tA' test.txt
      • 不幸的是,@LuisMuñoz \n 不可移植。
      • TryTryAgain - 我非常怀疑到目前为止我们看到的任何 sed 脚本是否是可移植的,一旦你使用 sed 转向 s/old/new/,你就会陷入非便携式结构。事件 \t 是不可移植的 - 您需要一个文字制表符来实现可移植性。
      【解决方案4】:

      这将在任何 UNIX 机器上的任何 shell 中使用任何 awk 工作:

      $ awk 'match($0,/".*"/){str=substr($0,RSTART,RLENGTH); gsub(/\t/,"\n",str); $0=substr($0,1,RSTART-1) str substr($0,RSTART+RLENGTH)} 1' file
      Name    Monitoring      Tags
      i-RBwPyvq8wPbUhn495 enabled "some:tags:with:colons=some:value:with:colons-and-dashes/and/slashes/yay606-values-001
      some:other:tag:with-colons-and-hypens=MACHINE NAME
      Name=NAMETAG
      backup=true"
      i-sMEwh2MXj3q47yWWP enabled "description=RANDOM BUSINESS INT01
      backup=true
      Name=SOMENAME"
      

      它只是从当前记录中提取"s 之间的字符串,用该字符串中的换行符替换所有制表符,然后在打印之前将记录重新组合在一起。

      【讨论】:

        猜你喜欢
        • 2014-03-18
        • 2020-08-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-01-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多