42985


linuxのsedコマンドでtest.txtの3番目に出現するLinuxをリナックスに置換したいです。

[code]

    test.txt
        Linux
        Linux
        Linux
        Linux
        Linux
    
[/code]

**私が実行したコマンド**  
`sed -i -e 's/Linux/リナックス/3' test.txt`

しかし実際には全ての行のLinuxがリナックスに置換されてしまいます。

[code]

    test.txt
        リナックス
        リナックス
        リナックス
        リナックス
        リナックス
    
[/code]

どなたか、アドバイスして頂けたら幸いです。

**捕捉**  
置換したい対象は行方向に見ていった時、何行目にあるいか分からないが、  
n番目(この場合は3番目)に出現するLinuxを置換したいというものです。

**置換対象のパターン**  
パターン1  
入力

[code]

    test.txt
        android
        Linux
        windows
        windows
        Linux
        macos
        Linux
        android
        Linux
    
[/code]

出力

[code]

    test.txt
        android
        Linux
        windows
        windows
        Linux
        macos
        リナックス<<3番目に出現したので置換
        android
        Linux
    
[/code]

パターン2  
入力

[code]

    test.txt
        android
        Linux
        windows
        windows
        LinuxLinux
        macos
        Linux
        android
        Linux
    
[/code]

出力

[code]

    test.txt
        android
        Linux
        windows
        windows
        Linuxリナックス<<3番目に出現したので置換
        macos
        Linux
        android
        Linux
    
[/code]

以上、よろしくお願いします。


CC BY-SA 3.0
2018-04-06T01:11:00.600
42973
2020-02-06T11:58:57.500
2018-04-06T04:57:57.917
27697
27697
question
linux sed
sedコマンドでn回目に出現する文字を置換する方法


3番目(=3行目)だけ置換する場合は以下を実行してみてください。

[code]

    $ cat test.txt | sed -e '3s/Linux/リナックス/'
    
[/code]

3行目～5行目、などのように範囲指定をする場合は以下になります。

[code]

    $ cat test.txt | sed -e '3,5s/Linux/リナックス/'
    
[/code]


CC BY-SA 3.0
2018-04-06T01:24:46.607
42974
2018-04-06T01:24:46.607
3060
42973
answer


sed ではむずかしいので、自分でしたら、 awk をつかうと思います。

[code]

    #!/bin/sh
    
    
    input() {
        cat <<EOF
    Linux
    linux
    Linux
    linux
    Linux
    linux
    Linux
    linux
    EOF
    }
    
    input | awk '/Linux/{c += 1;}
    c == 3 {
      gsub("Linux", "hogehoge", $0)
    }
    { print $0}
    '
    
[/code]

出力

[code]

    Linux
    linux
    Linux
    linux
    hogehoge
    linux
    Linux
    linux
    
[/code]


CC BY-SA 3.0
2018-04-06T01:43:03.943
42977
2018-04-06T01:43:03.943
754
42973
answer


[rou](https://ja.stackoverflow.com/users/8431/rou)さんの[回答](https://ja.stackoverflow.com/a/42989/25936)を参考にさせていただきました。

[code]

    sed -e '1{; :a; s/Linux/リナックス/3; t; N; ba; }' <test.txt
    
[/code]

1行目ならコマンドブロックを開始します。  
`a`というラベルを設定します。  
3番目のLinuxをリナックスに置換します。  
置換に成功したら末尾へ移動します。  
次の行をパターンスペースへ追加して、`a`というラベルへ移動します。  
コマンドブロックを終了します。


CC BY-SA 3.0
2018-04-06T03:54:40.797
42985
2018-04-06T05:24:07.567
2018-04-06T05:24:07.567
25936
25936
42973
answer


行をまたいで条件適用させるには、`N` で複数行を同時にパターンスペースに読み込む必要があります。  
`sed -i '-e 2,${;p;d;};:a;s/Linux/リナックス/3;t;N;ba' test.txt`

[code]

    1: 2,${
    2:   p
    3:   d
    4: }
    5: :a
    6: s/Linux/リナックス/3
    7: t
    8: N
    9: ba
    
[/code]

1～4行目と5～9行目が別ブロックになっています。  
アドレス指定により、ファイルの最初の行には5～9行目だけが適用されます。  
5～9行目はループになっており、3番目のLinuxの置換処理が成功すれば7行目から抜けます。  
見つからなければ8行目でファイルの次行を読み込み、マッチするまで繰り返します。

置換処理が完了した後は、残りの行に1～4行目が適用されます。  
入力行を加工せず出力するだけです。


CC BY-SA 3.0
2018-04-06T04:58:21.690
42989
2018-04-06T04:58:21.690
8431
42973
answer


GNU版sed(4.x)では、 `-z` オプションを利用できます。  
行単位ではなく標準入力全体を対象に処理が可能です。

  * 参考 : [sedで複数行にまたがった文字列を置換する方法 | ゲンゾウ用ポストイット](https://genzouw.com/entry/2019/09/09/085746)

[code]

    $ cat test.txt
        android
        Linux
        windows
        windows
        Linux
        macos
        Linux
        android
        Linux
    
    $ sed -z 's/Linux/リナックス/3' < test.txt
        android
        Linux
        windows
        windows
        Linux
        macos
        リナックス
        android
        Linux
    
[/code]

いかがでしょうか？


CC BY-SA 4.0
2020-02-06T11:58:57.500
62834
2020-02-06T11:58:57.500
34583
42973
answer