단일 명령의 여러 명령문이 작동하지 않습니다.

단일 명령의 여러 명령문이 작동하지 않습니다.

나는 약간의 딜레마에 빠졌습니다. 가능한 한 간단하게 설명하기 위해 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   

---- 그 자체로도 매우 유용합니다.

그러나 이를 하나의 명령으로 결합해야 하기 때문에 작동이 중지됩니다... 예를 들면 다음과 같습니다.

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을 실행한 것처럼 변경되지 않은 것으로 표시됩니다. (예, 두 번째로 파일을 영구적으로 편집하지 않을 것임을 알고 있습니다.)

이제 이해합니다. 예... 사용자가 시작할 수 있도록 파일 하단에 임시 항목을 추가한 다음 마지막 단계에서 제거하여 이 문제를 피할 수 있습니다. 또는 루프를 사용하여 스크립트를 실행할 수도 있고 작동할 수도 있지만 의도한 대로 단일 명령을 사용하여 이를 수행하는 더 우아한 방법이 있어야 합니다.

누구든지 아이디어가 있나요? 또한, 제가 원래 하려고 했던 일을 달성하는 더 좋은 방법이 있다면 알고 싶습니다.


편집: 입력/출력 예:

기본적으로 파일의 행은 다음과 같습니다.

%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를 사용하면 두 개의 "-e" 표현식이 포함된 두 번째 sed 명령이 제공된 예제 입력에서 제대로 작동합니다. (대부분의 경우. 마지막 줄은 2개의 주석 문자로 끝나지만 이는 큰 문제가 되지 않습니다.) sed여러 버전이 여러 표현식을 처리하는 방법에 약간의 차이가 있는지 확실하지 않습니까?

이것은 제가 선호하는 솔루션은 아니지만 sed가 여러 표현식으로 예측 가능하게 작동하도록 할 수 없는 경우 tee단일 sed 명령 파이프라인의 끝에서 사용할 수도 있습니다.

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

주석에서 몇 가지 설명을 한 후 먼저 편집하십시오.

추가하려는 줄이 sed가 실행되기 전에 주석 처리되면 첫 번째 정규식은 두 번째 주석 문자를 추가합니다. 줄 시작 부분에 두 개의 "#" 문자가 있으므로 두 번째 문은 더 이상 일치하지 않으며 아무 작업도 수행하지 않습니다. 간단한 편집은 두 번째 표현식의 "#" 문자에 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   

원래 답변:

귀하의 정규식에 대해 제가 착각하지 않았다면 두 번째 명령은 첫 번째 명령을 실행 취소하는 것입니다. 단순화된 예로서:

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

a각 줄은 여러 표현식을 순서대로 실행합니다 .

한 가지 옵션은 첫 번째 단계에서 대체 주석 구분 기호를 사용한 다음 세 번째 단계를 추가하여 이를 빼는 것입니다. 예를 들어 첫 번째 표현식의 줄 시작 부분에 "#"을 추가하는 대신 를 사용합니다 's/.*wheel/--&/'. 그런 다음 두 번째 표현식이 원하는 줄의 주석 처리를 제거한 후 세 번째 표현식을 추가하여 -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

관련 정보