sedまたはawk:文字列のn番目の項目のみを置き換える

sedまたはawk:文字列のn番目の項目のみを置き換える

以下を取るsed(またはその両方)を書く方法:awk

echo '1 aa 2 2 3 bb 5 bb 2 5' | sed/awk ...

そして、n番目の文字列だけを変更しますか?例えば第三登場か2、第二登場かbb

したがって、予想される出力は次のようになります(たとえば、2番目の項目を置き換える場合)bbreplaced

1 aa 2 2 3 bb 5 replaced 2 5

入力文字列、代替文字列はn任意の入力にすることができます。

答え1

sed2回目の発生を変更するために使用されます。bb

$ sed 's/bb/new-bb/2' file
1 aa 2 2 3 bb 5 new-bb 2 5

または 2 の 3 番目の発生を変更します。

$ sed 's/2/12/3' file
1 aa 2 2 3 bb 5 bb 12 5

答え2

1行目のn番目の発生位置を変更するには、sed構文は次s/pattern/replacement/3のとおりです。@HatLessはすでにデモしています。

入力全体のnperl番目の発生を変更するには、次のようにします。

perl -pse 'if($n>0) {s{pattern}{--$n ? $& : "replacement"}ge}' -- -n=3

答え3

一緒にawkできること:

awk -v str='bb' -v pos=2 -v rplc='newBB' '
 {
   strPos=0
   for(i=1; i<=NF; i++)
       if($i==str && (++strPos==pos) ) { $i=rplc; break }
 }1' infile

出力:

1 aa 2 2 3 bb 5 newBB 2 5

注:上記はフィールド区切り文字として1文字のみを想定しています(デフォルト:スペースまたはタブ)。それ以外の場合は、連続したフィールド区切り文字を1つに圧縮するか、awkが各単一フィールド区切り文字と個別に一致するように強制することができます(したがって、FSは正規表現として強制する必要があります)。パターン):

awk -F'[\t]' -v OFS='\t' -v str='bb' -v pos=2 -v rplc='newBB' '
 {
   strPos=0
   for(i=1; i<=NF; i++)
      if($i==str && (++strPos==pos) ) { $i=rplc; break }
 }1' infile

注:\tフィールド区切り文字が空白文字の場合は、空白文字に変更してください。


入力全体でn番目の項目を変更するには(ただし、フィールド区切り文字はタブであると仮定します):

awk -F'[\t]' -v OFS='\t' -v str='bb' -v pos=2 -v rplc='newBB' '
 strPos!=2{
            for(i=1; i<=NF; i++)
                if($i==str && (++strPos==pos) ) { $i=rplc; break }
 }1' infile

答え4

1つのコマンドで両方の操作を実行できますsed

echo "1 aa 2 2 3 bb 5 bb 2 5"|sed -e "s/2/kop/3" -e "s/bb/pp/2"

2このコマンドは、3番目の発生項目をwithにkop、2番目の発生項目をbbwithに置き換えますpp

関連情報