使用开始和结束模式连接多行

使用开始和结束模式连接多行

我有一个这样的文件:

method AAA one (1,111):
   some_text_1
method BBB two (2,
   222):
   tuesday
method CCC three (3,
    333):
   sunny_day
method DDD four (4,
    444_a,
    444_b):
   last_week

我希望它看起来像这样:

method AAA one (1,111):
   some_text_1
method BBB two (2,222):
   tuesday
method CCC three (3,333):
   sunny_day
method DDD four (4,444_a,444_b):
   last_week

我有这个 sed 命令几乎可以做到这一点:

sed -i '/method/,/):/ p; :a; N; $!b a; s/\n\s\{1,\}//g' file.txt

它给出了这个输出:

method AAA one (1,111):
method AAA one (1,111):some_text_1
method BBB two (2,222):tuesday
method CCC three (3,333):sunny_day
method DDD four (4,444_a,444_b): last_week

答案1

基于Sed 单行命令详解,第一部分:文件间距、编号和文本转换与替换,39. 如果一行以反斜杠“\”结尾,则将其追加到下一行,但将反斜杠更改为逗号并将替换扩展为包含以下空格:

$ sed -e :a -e '/,$/N; s/,\n[[:blank:]]*/,/; ta' file
method AAA one (1,111):
   some_text_1
method BBB two (2,222):
   tuesday
method CCC three (3,333):
   sunny_day
method DDD four (4,444_a,444_b):
   last_week

答案2

awk

awk 'f{sub(/^[[:space:]]+/, "")} {f=/,$/; ORS = f ? "" : RS} 1'

f每当行以 结尾时,这都会设置一个标志,。根据标志,输出记录分隔符将为空字符串或与输入记录分隔符相同(默认为换行符)。每当设置该标志时,下一行的起始空白字符也将被删除。


对于perl,假设输入足够小,可以作为单个字符串进行处理:

perl -0777 -pe 's/,\n\s*/,/g'

如果以 结尾的行,不是method函数的一部分,则上述解决方案将失败。在这种情况下,假设()该部分只有一对字符method,您可以使用:

perl -0777 -pe 's/method[^(]+\([^)]+\)/$&=~s|\n\s*||gr/ge'

这里method[^(]+\([^)]+\)将匹配从method到第一个()字符。替换部分有另一个 Perl 代码,它将作用于匹配部分以删除后跟可选空白字符的换行符。

答案3

使用gawk

awk 'function del_space(){gsub(/^\s+/,""); };
/,$/ {if (NR==l) del_space(); a=a $0; l=NR+1; next}
NR==l{del_space(); $0=a $0; a=""}1' file

只要在行尾找到逗号,变量a就会保存当前输入记录($0),后跟一个空格,然后是上一条记录。防止对此记录进行进一步的操作,即,当命令末尾使用 的打印惯用语时next,不会进行打印。awk1

在模式匹配后的下一个记录中,$0=a $0;a="";将当前输入记录($0)设置为a后跟旧的$0和变量分别a设置""

该函数在找到记录末尾del_space()后替换下一条记录开头的空格。,

如果你想要逗号后有一个空格,那么应该更改为:

awk 'function del_space(){gsub(/^\s+/,""); };
/,$/ {if (NR==l) del_space(); a=a $0; l=NR+1; next}
NR==l{del_space(); $0=a FS $0; a=""}1' file

答案4

另一个sed(POSIX):

sed ':a;/^method/!b;/[^:]$/N;s/[[:space:]]*\n[[:space:]]*/ /g;ta'
  • DEF标签:a
  • IF 模式空间不以method
    • 然后跳到结尾b
  • ELSE 如果它不以以下结尾:
    • 然后使用 追加下一行N
  • spaces* + \n+ spaces* 替换为' '
    • 如果有替换,则返回:a
  • 结束打印

应该处理类似的情况:

method XXX foo (8,
    888):
   bar,
   baz

method
HHH
bar
(
aa,
bb):
    lor

确实在参数周围留出了一些额外的空格。

相关内容