不要将所有大写字母用于非导出的变量名,以避免与导出的和/或内置的名称冲突。使用 GNU awk 将第三个 arg 用于 match() 并\S使用简写[^[:space:]]:
$ example='-----BEGIN CERTIFICATE----- line1 line2 line3 -----END CERTIFICATE-----'
$ printf '%s\n' "$example" |
awk 'match($0,/^(\S+ \S+)(.*)(\S+ \S+)$/,a){gsub(/ /,ORS,a[2]); print a[1] a[2] a[3]}'
-----BEGIN CERTIFICATE-----
line1
line2
line3
-----END CERTIFICATE-----
上面的脚本适用于任何输入。您应该尝试提出脚本可能失败的输入,以便能够测试任何建议的解决方案,以查看它是否真的有效,因为提出一个从一个特定示例输入产生预期输出的脚本很简单,并且想出一个适用于所有情况的解决方案要困难得多。
例如,一个重要且明显的测试示例是:
$ example='-----BEGIN CERTIFICATE----- -----BEGIN CERTIFICATE----- -----END CERTIFICATE----- -----END CERTIFICATE-----'
即,在 4 行证书本身中恰好巧合/不幸的是这些字符串:
- 第 1 行 =
-----BEGIN
- 第 2 行 =
CERTIFICATE-----
- 第 3 行 =
-----END
- 第 4 行 =
CERTIFICATE-----
输出应该是:
$ printf '%s\n' "$example" |
awk 'match($0,/^(\S+ \S+)(.*)(\S+ \S+)$/,a){gsub(/ /,ORS,a[2]); print a[1] a[2] a[3]}'
-----BEGIN CERTIFICATE-----
-----BEGIN
CERTIFICATE-----
-----END
CERTIFICATE-----
-----END CERTIFICATE-----
因此,如果任何建议的解决方案都无法正确处理,请不要使用该解决方案。
当前发布的其他答案均未正确处理:
拉文德的 awk:
$ printf '%s\n' "$example" |
awk '
match($0,/- .* -/){
val=substr($0,RSTART,RLENGTH)
gsub(/- | -/,"",val)
gsub(OFS,ORS,val)
print substr($0,1,RSTART) ORS val ORS substr($0,RSTART+RLENGTH-1)
}'
-----BEGIN CERTIFICATE-----
-----BEGIN
CERTIFICATE---------END
CERTIFICATE-----
-----END CERTIFICATE-----
saichovsky 的 seds 加管:
$ printf '%s\n' "$example" |
sed 's/- /-\n/g; s/ -/\n-/g' | sed '/CERTIFICATE/! s/ /\n/g'
-----BEGIN CERTIFICATE-----
-----BEGIN CERTIFICATE-----
-----END CERTIFICATE-----
-----END CERTIFICATE-----
anubhava 的 perl:
$ perl -pe 's/(?:BEGIN|END) CERTIFICATE(*SKIP)(*F)|\h+/\n/g' <<< "$example"
-----BEGIN CERTIFICATE-----
-----BEGIN CERTIFICATE-----
-----END CERTIFICATE-----
-----END CERTIFICATE-----