sed + 最初の一致または2番目の一致から文字を削除する

sed + 最初の一致または2番目の一致から文字を削除する

次のsed構文は、「すべて付与が必要」行から「#」を削除します。

   sed 's/#\([[:space:]]*Require all granted\)/ \1/' graphite-web.conf

   #<IfModule mod_authz_core.c>
   #    # Apache 2.4
   #    Require local
   #    Order Allow,Deny
   #    Allow from All
        Require all granted
   #</IfModule>
   #<IfModule !mod_authz_core.c>
   #    # Apache 2.2
        Require all granted
   #    Order Allow,Deny
   #    Deny from all
   #    Allow from All
   #    Allow from ::1
   #</IfModule>

最初の一致から "#"を削除するようにsed構文を変更するにはどうすればよいですか?それとも2番目のゲーム?

予想出力:

   #<IfModule mod_authz_core.c>
   #    # Apache 2.4
   #    Require local
   #    Order Allow,Deny
   #    Allow from All
        Require all granted
   #</IfModule>
   #<IfModule !mod_authz_core.c>
   #    # Apache 2.2
   #    Require all granted
   #    Order Allow,Deny
   #    Deny from all
   #    Allow from All
   #    Allow from ::1
   #</IfModule>

または

   #<IfModule mod_authz_core.c>
   #    # Apache 2.4
   #    Require local
   #    Order Allow,Deny
   #    Allow from All
   #    Require all granted
   #</IfModule>
   #<IfModule !mod_authz_core.c>
   #    # Apache 2.2
        Require all granted
   #    Order Allow,Deny
   #    Deny from all
   #    Allow from All
   #    Allow from ::1
   #</IfModule>

答え1

awk代わりに使用

$ cat ip.txt 
   #    Allow from All
   #    Require all granted
   #    # Apache 2.2
   #    Require all granted
   #    Order Allow,Deny
   #    Require all granted
   #    Order Deny

$ awk '/#[[:space:]]*Require all granted/ && ++c==1{sub("#", " ")} 1' ip.txt
   #    Allow from All
        Require all granted
   #    # Apache 2.2
   #    Require all granted
   #    Order Allow,Deny
   #    Require all granted
   #    Order Deny

$ awk '/#[[:space:]]*Require all granted/ && ++c==2{sub("#", " ")} 1' ip.txt
   #    Allow from All
   #    Require all granted
   #    # Apache 2.2
        Require all granted
   #    Order Allow,Deny
   #    Require all granted
   #    Order Deny

$ awk '/#[[:space:]]*Require all granted/ && ++c>1{sub("#", " ")} 1' ip.txt
   #    Allow from All
   #    Require all granted
   #    # Apache 2.2
        Require all granted
   #    Order Allow,Deny
        Require all granted
   #    Order Deny

また、見ることができますawk は変更内容を保存します。


または以下を使用してください。perl

$ # for inplace editing, use perl -i -pe
$ perl -pe 's/#/ / if /#\s*Require all granted/ && ++$c==1' ip.txt
   #    Allow from All
        Require all granted
   #    # Apache 2.2
   #    Require all granted
   #    Order Allow,Deny
   #    Require all granted
   #    Order Deny

答え2

またはsed方法:

sed ':a;N;$!ba;s/#\([[:space:]]*Require all granted\)/ \1/2' graphite-web.conf

入力ファイルに以下が含まれている場合:

#<IfModule mod_authz_core.c>
   #    # Apache 2.4
   #    Require local
   #    Order Allow,Deny
   #    Allow from All
   #    Require all granted
   #</IfModule>
   #<IfModule !mod_authz_core.c>
   #    # Apache 2.2
   #    Require all granted
   #    Order Allow,Deny
   #    Deny from all
   #    Allow from All
   #    Allow from ::1
   #</IfModule>

出力は次のとおりです。

#<IfModule mod_authz_core.c>
   #    # Apache 2.4
   #    Require local
   #    Order Allow,Deny
   #    Allow from All
   #    Require all granted
   #</IfModule>
   #<IfModule !mod_authz_core.c>
   #    # Apache 2.2
        Require all granted
   #    Order Allow,Deny
   #    Deny from all
   #    Allow from All
   #    Allow from ::1
   #</IfModule>

このモードは、:a;N;$!ba;ファイルの終わり(例えば、whileループ)より前のすべての行を読み取り、s///2eofが到着した後に2番目の発生で置換を実行します。

あなたが読んだsedタグの最高の説明:a;$!N; とはどういう意味ですか? sedコマンドで?

同様のトピックを読んでsedを使用してn番目の文字列を置き換える方法

答え3

ストリームで動作するように設計されています。必要なものを達成する簡単な方法は、次を使用することですed

ed -s graphite-web.conf <<<$'/Require all/s/#/ /\nw'

アップデート:詳しく説明できますが、edこれはページedより詳細に説明し、広く使用されています。

この行の私の解釈は次のとおりです。

-sそれはかなり意味です。私たちが何を変えたのか見せないでください。

次にherestringを使用し、バックスラッシュ文字の組み合わせが拡張される<<<ANSI C形式の引用を適用します。新しい行を追加してファイルに書き込むという意味です。$''\nw

答え4

バージョンは次のとおりです...変更する回数を示す数字でexシェル変数を設定します(たとえば、このコマンドを使用すると、パターンの2回目の出現が修正されます)...xx=2

これにより、入力ファイルが更新されます。

ex +'/#\(\s*Require all granted\)/|1' +"norm ${x}n" +'s// \1/|wq' file 

これはファイルを変更しませんが、変更されたバージョンを印刷するパイプのバリエーションです。標準出力:

cat file | ex +'/#\(\s*Require all granted\)/|1' +"norm ${x}n" +'s// \1/' +'%p|q!' /dev/stdin

詳細:

インタラクティブに実行されない場合は、ex基本的にバッチ処理のコマンドラインモード中心バージョンであるため、多くのコンテンツがvimユーザーフレンドリーであるvim必要があります。

  • /#\(\s*Require all granted\)/|1- パターンを検索し、1行目「Reset」に移動します。
  • norm ${x}nn- パターンタイムxの最後の発生位置に移動
  • s// \1/|wq- 現在行のみを交換して書き込み終了

関連情報