【问题标题】:sed / awk - remove newline with conditionsed / awk - 删除有条件的换行符
【发布时间】:2019-12-01 17:20:00
【问题描述】:

我有以下文字:

pane    0   1   :title  1   :*  1   :/home/user 0   app1name    :
app1 -some -stuff
pane    0   1   :title  1   :*  2   :/home/user 0   app2name    :
pane    0   1   :title  1   :*  3   :/home/user 1   app3name    :
app3
window  0   1   1   :*  somelongstuff
state   0   

我想要实现的是在结束 : 后删除换行符,但仅当以下行不以 pane\twindow\t 开头时

所以最终的输出应该是这样的:

pane    0   1   :title  1   :*  1   :/home/user 0   app1name    :app1 -some -stuff
pane    0   1   :title  1   :*  2   :/home/user 0   app2name    :
pane    0   1   :title  1   :*  3   :/home/user 1   app3name    :app3
window  0   1   1   :*  somelongstuff
state   0   

我尝试了几种sed和awk,比如 sed '/\npane\t/ n; /window\t/ n; N; s/:\n/:/g'awk '{ORS=(/pane\t/?"":RS)}1' 但在某种程度上他们都失败了

谁能帮帮我?

【问题讨论】:

  • 将这些努力发布到问题中
  • @Inian 根据要求我添加了几次(失败的)尝试

标签: awk sed newline


【解决方案1】:

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

sed 'N;/:\n/{/\n\(pane\|window\)/!s/\n//};P;D' file

在整个文件长度上打开一个两行的窗口。如果第一行以: 结尾,而第二行不以panewindow 开头,则删除换行符。打印/删除第一行并重复。

或者,经过反思:

sed 'N;/:\n\(window\|pane\)/!s/:\n/:/;P;D' file

【讨论】:

  • 由于这个 sed 命令不考虑 : 可能删除 \n 我应该注意排除 state (最后一行关键字)。并且可能在窗格、窗口和状态之后添加\t,以更好地确保它不应该删除\n。想出了这个:sed 'N;/\n\(pane\t\|window\t\|state\t\)/!s/\n//;P;D' file,这似乎有效。我说的对吗?
【解决方案2】:

在每个 UNIX 机器上的任何 shell 中使用任何 awk:

$ awk 'NR>1{printf "%s%s", p, ((p ~ /:$/) && !/^(pane|window)\t/ ? "" : ORS)} {p=$0} END{print p}' file
pane    0       1       :title  1       :*      1       :/home/user     0       app1name        :app1   -some   -stuff
pane    0       1       :title  1       :*      2       :/home/user     0       app2name        :
pane    0       1       :title  1       :*      3       :/home/user     1       app3name        :app3
window  0       1       1       :*      somelongstuff
state   0

【讨论】:

    【解决方案3】:

    sed 不太适合这个任务。您将不得不摆弄 sed 的保持空间以使其工作。到那时,切换到另一个工具会更容易。

    这是一个perl 脚本

    perl -np0 -e 's/:\n(?!pane\t|window\t)/:/g'
    

    在管道中使用它或将文件名作为参数传递。

    【讨论】:

      【解决方案4】:

      Perl 来救援!

      perl -pe 'print "\n" if $chomped && /^(pane|window)\t/; $chomped = /:$/ ? chomp : 0' -- file
      
      • -p逐行读取输入,处理后打印每一行
      • chomp 删除尾随换行符(如果存在)。它还返回删除的字符数。
      • 如果冒号是一行的最后一个字符,/:$/ 匹配。
      • ? : 是三元运算符。如果条件为真,即如果冒号是一行中的最后一个字符,我们删除换行符(如果存在)并将 $chomped 变量设置为 1,否则设置为 0。
      • 读取一行时,$chomped 变量告诉我们是否从前一行中删除了换行符。如果是,但当前行以panewindow 开头,后跟\t,我们将换行插入回去。

      【讨论】:

        猜你喜欢
        • 2012-07-25
        • 2019-08-31
        • 2020-11-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-10-29
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多