给定一个字符串,如果逗号前面没有字符,并且在每个没有字符的逗号之间,,a,,,b,,,,
,我想-
在开头强加该字符。意思是结果是-,-,a,-,-,b,-,-,-,-
.现在,我已经尝试过:
echo ",,a,,,b,,,," | sed 's/,/,-/g' | sed 's/-\([^,]\)/\1/g' | sed 's/^,/-&/g'
导致:-,-,a,-,-,b,-,-,-,-
但问题是,调用 sed 3 次效率很低非常长的迭代有没有办法用 sed 来做到这一点,可能使用正则表达式,或任何其他工具调用一次?
答案1
(echo ,,a,,,b,,,,; echo a,,b) | perl -pe 's/(^|,)\K(?=(,|$))/-/g'
-,-,a,-,-,b,-,-,-,-
a,-,b
我想我应该学习sed
这些年之一。
答案2
一这样做的方法sed
是使用循环:
$ echo ",,a,,,b,,,," | sed ':a; s/\(^\|,\)\(,\|$\)/\1-\2/; ta'
-,-,a,-,-,b,-,-,-,-
如果您的版本支持扩展正则表达式,您可以将其简化为更具可读性
sed -E ':a; s/(^|,)(,|$)/\1-\2/; ta'
另一种方法是在 中执行此操作perl
,拆分为逗号分隔的字段,然后将空字段映射到连字符:
perl -anle 'print join ",", map { $_ ? $_ : "-" } split(",", $_, -1)'
(强制包含尾随空字段的附加-1
参数)。split
答案3
echo ",,a,,,b,,,," |
awk -v 'FS=,' -v 'OFS=,' '{for (i=1; i<=NF; i++) sub(/^$/,"-",$i); print};'
答案4
$ echo ',,a,,,b,,,,' | sed 's/\(\([^,]\+,\)*\),/\1-,/g; s/\(^\|,\)$/\1-/'
-,-,a,-,-,b,-,-,-,-
第二个表达式(s/\(^\|,\)$/\1-/
) 是必需的,只是因为sed
当它到达模式空间的末尾时似乎停止匹配,即使$
如果唯一的表达式是 ,它仍然可以匹配 a s/\(\([^,]\+,\)*\)\(,\|$\)/\1-\3/g
。
当然,sed -E
这使它更具可读性,但在其他方面是等效的:
sed -E 's/(([^,]+,)*),/\1-,/g; s/(^|,)$/\1-/'