如何使用 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>/
位此处包含一个文字制表符,尽管某些sed
s 可能也支持\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
解释
在以字母字符开头的行上,如果有的话,它会拉入下一个,然后,如果它可以寻址后跟非字母字符的换行符,它会选择模式空间中的所有内容,直到最后一个换行符,然后执行其替代品 - 将最后一个新行更改为制表符。但如果没有,它会返回并再次尝试。