![仅替换字符的第一个实例](https://linux22.com/image/91112/%E4%BB%85%E6%9B%BF%E6%8D%A2%E5%AD%97%E7%AC%A6%E7%9A%84%E7%AC%AC%E4%B8%80%E4%B8%AA%E5%AE%9E%E4%BE%8B.png)
例如我有 scv 文件,看起来像
a1, b1, c1, d1
a2, b2, c2, d2
a3, b3, c3, d3
我想要做的是将第一个逗号替换,
为分号;
。第一个逗号的位置可以是可变的(a
在行中n
并且m
可以有不同的长度)。最后我的文件看起来像
a1; b1, c1, d1
a2; b2, c2, d2
a3; b3, c3, d3
其他逗号必须保留。有人可以告诉我最简单的解决方案吗?
PS我的解决方案不起作用:sed '/s/,/;/g' file.csv
答案1
中g
:
sed 's/,/;/g'
是为了全球,即将所有出现的 替换,
为;
。
如果您只想每行进行一次替换,请去掉g
:
sed 's/,/;/'
为了完整性:
您还可以指定要替换的出现次数。例如,仅替换第二次出现的情况:
sed 's/,/;/2'
使用 GNU sed
,您还可以将从第二个开始的所有出现(实际上,除了第一个之外的所有出现)替换为:
sed 's/,/;/2g'
要执行两次替换,在本例中:
sed 's/,/;/;s/,/;/'
当模式可以匹配替换(或其部分)时,情况会变得更加复杂,例如用 替换,
时<,>
。sed
没有内置机制来解决这个问题。perl
在这种情况下,您可能想改用:
perl -pe '$i = 0; s/,/$i++ < 2 ? "<,>" : $&/ge'
perl -pe
isperl
的sed
模式(请注意,正则表达式语法不同)。有了操作符e
的标志s///
,替换就被认为是代码。在那里,我们仅当增量计数器 < 2 时才替换,
with 。否则,我们将替换为自身(实际上指的是匹配的字符串,如in的命令)。<,>
,
$&
&
sed
s
您可以将其概括为一系列或一组替换。就像第 3到5 个和第 7到9个一样:
perl -pe '$i = 0; s/,/$i++;
$i >=3 && $i <= 5 || $i >= 7 && $i <= 9 ? "<,>" : $&/ge'
仅替换第一次出现的位置在整个输入中(相对于在每一行):
sed -e 's/,/;/;t done' -e b -e :done -e 'n;b done'
也就是说,在第一次成功替换后,进入一个仅打印其余输入的循环。
使用 GNU sed
,您可以使用伪地址0:
sed '0,/,/s//;/'
笔记
我想这是一个错字,但是
sed '/s/,/;/g'
你在问题中写的命令是完全不同的。
那是在做:
sed '/start/,/end/g'
哪里start
是s
和end
是;
.也就是说,g
对文件中包含 的部分s
和下一个包含;
.
答案2
纯的巴什解决方案
while IFS=\, read -r a b ; do echo "$a;$b" ; done <file.csv
或者只是为了好玩
paste -d\; <(cut -d, -f1 file.csv) <(cut -d, -f1 --complement file.csv)