用 sed 替换包含模式的行

用 sed 替换包含模式的行

如何使用 sed 替换与模式匹配的行中的给定字符?

例如:我想匹配以字母开头的每一行,并用制表符替换末尾的换行符。我正在尝试使用:(sed -e '/^[A-Z]/s/\n/\t/g'我感兴趣的行也始终以字母结尾,如果这有帮助的话)。

输入样本

NAME_A
12,1
NAME_B
21,2

样本输出

NAME_A    12,1
NAME_B    21,2

答案1

sed '/^[[:alpha:]]/{$!N;s/\n/       /;}' <<\DATA
NAME_A
12,1
NAME_B
21,2
DATA

输出

NAME_A  12,1
NAME_B  21,2

它处理以字母开头的行,如果有则拉入下一个,并用制表符替换换行符。

请注意,该s/\n/<tab>/位此处包含一个文字制表符,尽管某些seds 可能也支持\t在其位置进行转义

要处理递归情况,您需要使其更加健壮,如下所示:

sed '$!N;/^[[:alpha:]].*\n[^[:alpha:]]/s/\n/    /;P;D' <<\DATA
NAME_A
NAME_B
12,1  
NAME_C
21,2
DATA

输出

NAME_A
NAME_B  12,1
NAME_C  21,2

它总是在数据集前面滑动一行。如果两^[[:alpha:]]行相继出现,它不会错误地替换换行符,如您所见。

答案2

另一个解决方案:

sed -e :a -e '$!N;s/\n\([^[:alpha:]]\)/ \1/;ta' -e 'P;D'

如果当前行不以 Alphabeta 开头,则将当前行附加到上一行。

更新

经过我们讨论后@mikerserv 提出的解决方案:

sed ':a
/^[[:alpha:]]/{$!N;/\n[^[:alpha:]]/!ba;s/\(.*\)\n/\1\t/}
' file

解释

在以字母字符开头的行上,如果有的话,它会拉入下一个,然后,如果它可以寻址后跟非字母字符的换行符,它会选择模式空间中的所有内容,直到最后一个换行符,然后执行其替代品 - 将最后一个新行更改为制表符。但如果没有,它会返回并再次尝试。

相关内容