web-dev-qa-db-ja.com

キャラクターの最初のインスタンスのみを置き換える

たとえば、私は次のような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

3
Guforu

純粋bashソリューション

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)
3
Costas

g

sed 's/,/;/g'

globally用です。つまり、すべての,;で置き換えます。

1行につき1つだけ置換したい場合は、gを外します。

sed 's/,/;/'

そして完全性のために:

置換するオカレンスを指定することもできます。たとえば、2番目のオカレンスのみを置き換えるには、次のようにします。

sed 's/,/;/2'

GNU sedを使用すると、2番目のものから始まるすべてのオカレンス(つまり、最初のものを除くすべて)を次のもので置き換えることもできます。

sed 's/,/;/2g'

この場合、2つの置換を実行するには:

sed 's/,/;/;s/,/;/'

より複雑になるのは、パターンが置換(またはその一部)に一致する場合です。たとえば、,<,>で置換する場合などです。 sedには、これに対処するための組み込みメカニズムがありません。その場合は、代わりにPerlを使用できます。

Perl -pe '$i = 0; s/,/$i++ < 2 ? "<,>" : $&/ge'

Perl -pePerlsedモードです(正規表現の構文が異なることに注意してください)。 s///演算子のeフラグを使用すると、置換はコードと見なされます。そこでは、インクリメントされたカウンターが2未満の場合にのみ、,<,>に置き換えます。それ以外の場合は、,をそれ自体に置き換えます($&は、実際にsedsコマンドで&のような一致した文字列を参照します)。

ある範囲または一連の置換に対してそれを一般化できます。 3のようにrd 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を使用すると、疑似アドレスを使用できます。

sed '0,/,/s//;/'

注意

それはタイプミスだと思いますが、

sed '/s/,/;/g'

あなたがあなたの質問に書いたコマンドは、まったく違うものです。

それはやっています:

sed '/start/,/end/g'

ここで、startsで、end;です。つまり、gを含むファイルの間にあるファイルのセクションにsコマンドを適用する(パターンスペースをホールドスペースのコンテンツで置き換える(ここでは何も保持しないので空))そして、次は;を含むものです。

14