単一コマンドの複数のステートメントが機能しません。

単一コマンドの複数のステートメントが機能しません。

私は少しジレンマに陥った。できるだけ簡単に説明するために、sedを使用してLinuxで/ etc / sudoersファイルを編集するスクリプトの一部を作成しようとしています。私が使用しているアカウントのためにこの編集作業を実行するには、sudoを使用してsedコマンドを実行する必要があります。ただし、このため、ファイルのすべての編集が完了するまでコマンドを終了することはできません。それ以外の場合はロックされます。

特に/etc/sudoersファイルで%wheelグループを変更しようとしましたが、さまざまなサーバー上のファイルに既存のエントリがありました。独自の最適化項目を追加し、前の項目をコメントアウトし、最後に追加した項目がコメントアウトされていないことを確認したいと思います。

これを行うために、sedにステートメントを作成しましたが、個別にうまく実行されます。同じコマンドで複数のステートメントを受け入れようとすると、どちらのステートメントも機能しません。 (構文エラーが発生しなくても)

たとえば、私の声明は次のとおりです。

sudo sed 's/.*wheel/#&/' /etc/sudoers

----効果自体はとても良いです

sudo sed 's/^#\s*\(%wheel\s\+ALL=(ALL)\s\+NOPASSWD:\s\+LOG_INPUT:\s\+LOG_OUTPUT:\s\+ALL\)/\1/' /etc/sudoers   

----それ自体でも非常に便利です。

ただし、これを1つのコマンドにまとめる必要があるため、動作は停止します...たとえば、次のようになります。

sudo sed 's/(.*wheel/#&) (^#\s*\(%wheel\s\+ALL=(ALL)\s\+NOPASSWD:\s\+LOG_INPUT:\s\+LOG_OUTPUT:\s\+ALL\))/' /etc/sudoers   -

---いいえ、サイコロはありません。

または

sudo sed -e 's/.*wheel/#&/' -e 's/^#\s*\(%wheel\s\+ALL=(ALL)\s\+NOPASSWD:\s\+LOG_INPUT:\s\+LOG_OUTPUT:\s\+ALL\)/\1/' /etc/sudoers   

----やはり動作しません

ちょっと待って、この問題を解決する方法はありません。上記の2つのコマンドを実行した後の出力には、元のファイルでcatを実行したかのように変更されていないとマークされます。 (はい、2番目にファイルを永久に編集しないことを知っています。)

今理解しています。はい...ユーザーが起動できるように、ファイルの下部に一時エントリを追加してから、最後の手順で削除してこの問題を回避できます。あるいは、ループを使用してスクリプトを実行することも、機能することもできますが、意図したとおりに単一のコマンドを使用してこれを実行するよりエレガントな方法が必要です。

誰にもアイデアがありますか?また、私が最初にやろうとしていたことを達成するより良い方法がある場合は知りたいです。


編集:入力/出力の例:

デフォルトでは、ファイルの行は次のようになります。

%wheel  ALL=(ALL)       ALL
%wheel  ALL=(ALL) NOPASSWD: LOG_INPUT: LOG_OUTPUT: ALL   ---added by me in a previous step
#%wheel  ALL=(ALL)       NOPASSWD: ALL

私はsedを実行した後の最終製品が次のようになりたいと思います。

#%wheel  ALL=(ALL)       ALL
%wheel  ALL=(ALL) NOPASSWD: LOG_INPUT: LOG_OUTPUT: ALL   
#%wheel  ALL=(ALL)       NOPASSWD: ALL

いいえうまくいけば、次のようになります。

#%wheel  ALL=(ALL)       ALL
#%wheel  ALL=(ALL) NOPASSWD: LOG_INPUT: LOG_OUTPUT: ALL   
#%wheel  ALL=(ALL)       NOPASSWD: ALL

そして私いいえうまくいけば、次のようになります。

%wheel  ALL=(ALL)       ALL
%wheel  ALL=(ALL) NOPASSWD: LOG_INPUT: LOG_OUTPUT: ALL   
%wheel  ALL=(ALL)       NOPASSWD: ALL

現時点では、マルチステートメントのsedコマンドは何もしないように見えますが、それを別のコマンドとして実行するだけで必要な出力が得られます。 (この場合はできません)

どんな助けでも大変感謝します!

答え1

元の質問に例を追加した後の最終編集:

Debian Jessie/sed(GNU sed) 4.2.2 では、2 つの "-e" 式を含む 2 番目の sed コマンドが提供された入力例で正しく動作します。 (ほとんどの場合、最後の行は2つのコメント文字で終わりますが、これは大きな問題ではありません。)sed複数のバージョンが複数の式を処理する方法に多少の違いがあるかどうかはわかりませんか?

これは私が好む解決策ではありませんが、sedが複数の式で予測可能に動作することができない場合は、単一のteesedコマンドパイプラインの末尾で使用することもできます。

sudo cat /etc/sudoers | { multiple sed commands in pipeline } | sudo tee /etc/sudoers

コメントでいくつかの説明をした後、まず編集します。

追加したい行が sed が実行される前にコメントアウトされると、最初の正規表現は 2 番目のコメント文字を追加します。行の先頭には2つの「#」文字があるため、2番目のステートメントは一致しなくなり、何もしません。簡単な編集は、2番目の式の「#」文字に1つ以上の修飾子を使用することです。

sudo sed -e 's/.*wheel/#&/' -e 's/^#\+\s*\(%wheel\s\+ALL=(ALL)\s\+NOPASSWD:\s\+LOG_INPUT:\s\+LOG_OUTPUT:\s\+ALL\)/\1/' /etc/sudoers   

元の答え:

あなたの正規表現について私が間違っていなかった場合、2番目のコマンドは最初のコマンドを元に戻すことです。単純化された例として:

echo a | sed -e 's/a/b/' -e 's/b/a/'

a各行は複数の式を順番に実行します。

1つのオプションは、最初のステップで代替コメント区切り文字を使用してから、3番目のステップを追加してそれを減算することです。たとえば、最初の式の行の先頭に "#"を追加する代わりにを使用します's/.*wheel/--&/'。次に、2番目の式が目的の行のコメントを外した後、3番目の式を追加してクリーンアップします-e 's/^--/#/'

答え2

OPがすべての行を表示する必要があることをどのように理解していますか?ホイールコメントで(テキストに加えて)%wheel\s\+ALL …

sudo sed '
    /%wheel\s\+ALL=(ALL)\s*NOPASSWD:\s*LOG_INPUT:\s*LOG_OUTPUT:\s*ALL/{
        s/^#\+\s*//
        b
    }
    /^[^#].*wheel/s/^/#/
    ' /etc/sudoers

関連情報