여러 줄 텍스트 처리: sshd_config 편집

여러 줄 텍스트 처리: sshd_config 편집

sshd_config 파일 끝에 다음과 같이 여러 블록이 있습니다.

Match User FOO
    ChrootDirectory /srv/www/FOO
    AllowTCPForwarding no
    X11Forwarding no
    ForceCommand internal-sftp

Bash 스크립트에서 이 블록(FOO1, FOO2 등과 관련된 다른 블록은 제외)을 제거하려면 어떻게 해야 합니까?

답변1

모든 Match블록이 파일 끝에 있다고 가정합니다 sshd_config.
블록이 빈 줄로 구분된 경우 예를 들면 다음과 같습니다.

Match User FOO1
    PasswordAuthentication no

Match User FOO2
    PasswordAuthentication yes

Match User FOO
    ChrootDirectory /srv/www/FOO
    AllowTCPForwarding no
    X11Forwarding no
    ForceCommand internal-sftp

Match User FOO그런 다음 첫 번째 빈 줄 까지(및 포함) 줄에서 삭제합니다 .

sed '/^Match User FOO$/,/^$/d' sshd_config

예를 들어 분리되지 않은 경우:

Match User BAZ
    PasswordAuthentication yes
Match User FOO
    ChrootDirectory /srv/www/FOO
    AllowTCPForwarding no
    X11Forwarding no
    ForceCommand internal-sftp
Match User FOO1
    PasswordAuthentication no
Match User FOO2
    PasswordAuthentication yes

그런 다음 Match User FOO다음으로 시작하는 첫 번째 줄까지 삭제합니다(포함하지 않음) Match.

sed '/^Match User FOO$/,/^Match.*/{//!d;/^Match User FOO$/d;}' sshd_config

sed -i ...파일의 내부 편집을 사용해야 합니다 . sed자세한 내용/백업 옵션은 설명서를 확인하세요 .

답변2

send 및 awk 도구를 사용하여 이 스크립트를 시도해 볼 수 있습니다.

matchedLine=$(awk '/Match User FOO1/{ print NR; exit }' $1) 


if [ "$matchedLine" = "" ];then
echo "Match not found"
exit 1;
fi

sed -e "$matchedLine,$(awk "BEGIN {print $matchedLine + 5 }";)d;" $1

스크립트는 SSH 구성 파일의 파일 이름을 첫 번째 인수로 사용합니다. 그런 다음 일치하는 문자열(이 경우 "사용자 FOO1과 일치")이 처음 나타나는지 파일을 검색합니다. 일치하는 항목이 발견되면 줄 번호를 $matchedLine 변수에 저장합니다. 마지막으로 sed를 사용하면 텍스트와 일치하는 줄과 다음 5줄이 삭제됩니다. 이 스크립트는 실제 파일을 편집하지 않으며 일치하는 줄이 제거된 파일 내용만 표시합니다. 이렇게 하면 위험 없이 스크립트가 제대로 작동하는지 확인할 수 있습니다. 실제 파일을 편집하려면 sed 명령을 파일로 리디렉션하면 됩니다.

답변3

sed '/^Match User FOO$/,/^  *F.*-sftp$/c\ 
    The whole of the above line range is \
    replaced with this one block of text.\
    Use an empty "c"hange command or a   \
    "d"elete command to replace it with  \
    nothing at all.' <infile >outfile

그건 그렇고, 들여쓰기에 의존할 수 있는 것 같습니다. 어쩌면 이렇게 할 수도 있습니다:

sed '$!N;/^Match User FOO\n/,/\n[[:upper:]]/!P;D
'    <infile >outfile

다음 입력 라인을 관찰하면서 현재 라인 삭제를 시작합니다.성냥블록이 발견되었습니다. 다음 입력 줄이 대문자로 시작하면 삭제를 중지합니다.

위의 명령에는 더 나은 설명이 필요할 수 있습니다. 이것이 제가 아는 가장 간단하고 믿을 수 있는 방법입니다.

워크플로는 다음과 같습니다.

  1. !$마지막 입력 라인 이 아닌 각 입력 라인에 대해 N추가 입력 라인도 패턴 공간에 추가됩니다.

    • 일반적으로 한 번에 한 행만 작동하는 것으로 알려져 있지만 sed이는 기본 동작일 뿐입니다. sed편집개울원하는 대로 맞춤 설정할 수 있습니다.
    • 이 경우 Next 명령은 다음 행을 소개합니다.시야이는 다른 두 명령의 도움으로 스크립트 전체에서 지속됩니다.
  2. 그런 다음 현재 컨텍스트가/2/,/address/ 범위지정된 행 수입니다.

    • /^Match User FOO\n/- 범위시작일치하는 패턴이 이미 주기의 패턴 공간에 있고 그렇지 않으면 P표준 출력으로 인쇄될 때. 이는 패턴 공간의 선두로 표현됩니다.^그리고 \n패턴의 후행 Ewline입니다. 패턴은 처음부터 끝까지 전체 입력 라인을 나타냅니다.언제든지 패턴 공간.
    • /\n[[:upper:]]/- 이것은 대부분 예제와 예제에 대한 나의 명백한 들여쓰기 스타일을 기반으로 합니다.sshd_config이는 다음을 나타냅니다.모두관련 명령 기본 요소는 대문자로 시작됩니다.
    • \n패턴의 선두 ewline 이스케이프와 결합하면 sed범위의 일치하는 컨텍스트는 ext로 가져온 행이 1 -로 시작하는 경우에만 종료됩니다.N아니요공백이 있으면 됩니다.
  3. 범위 내에 있지 않으면 !패턴 공간의 P첫 번째 ewline 문자가 \n표준 출력으로 인쇄되지만, 범위 내에 있으면 현재 주기에서는 아무것도 인쇄되지 않습니다.

  4. 마지막으로, 패턴 공간에서 처음으로 나타나는 ewline이 D삭제 되고 현재 루프가 종료됩니다.\n

    • 이것은 매우 중요합니다 - Delete는 그렇습니다아니요다음 사이클이 시작될 때 새 입력 라인을 끌어옵니다.~하지 않는 한\n현재 패턴 공간에는 0개의 행이 있습니다.
    • 있을 때\nelete는 패턴 공간의 줄바꿈으로, D남은 내용이 포함된 새 루프로 재귀되기 전에 해당 내용까지의 내용만 지웁니다. 실제로 제거되는 것은 범위와 일치하지 않는 컨텍스트에서 rint가 표준 출력에 쓴 내용 D뿐입니다 .P

이제 이 모든 것은 내가 이전에 말한 것을 말하는 매우 기술적인 방법입니다. 일치 범위의 시작부터 들여쓰기 수준의 끝까지, 그리고 줄 시작 부분에서 대문자로 시작하는 새로운 명령을 찾는 것은 아무것도 아닙니다. 다른 모든 것은 인쇄되는 동안 인쇄됩니다. 따라서 블록은 들여쓰기에 따라 매우 간단한 방식으로 출력에서 ​​제거되며 들여쓰기로만 선택을 제어할 수 있습니다.성냥이미 했던 것처럼 차단하세요.

이제 이 모든 것을 완전히 이해하려면 루프를 이해해야 sed하지만 l작동 방식을 자세히 살펴보면 이해하기 쉽습니다.

seq 10 | sed '$!N;/^4\n/,/\n9/!P;l;D'

위 명령은 두 가지 다른 이유로 인쇄됩니다.(해당되는 경우)범위 일치 컨텍스트 입니다 !P. 이는 위에서 제안한 표준 출력입니다.

두 번째는 l그것이 어떻게 작동하는지에 대한 우리의 이해 입니다 sed. 나는 그것을 인쇄하라고 말합니다.모든루프 패턴 공간의 현재 내용을 명시적으로 표현합니다. 결과는 다음과 같습니다.

1             #This is Printed before we look at pattern space.
1\n2$         #This is our look - though only the 1st line is printed,
2             #each time one is, pattern space is actually 2 lines
2\n3$         #all of the time - it's our window into future output.
3
3\n4$         #3 prints, though 4 is in pattern space. But when pattern
4\n5$         #space matches ^4\n as it does now, nothing prints.
5\n6$
6\n7$         #And continues not to print...
7\n8$
8\n9$         #until the range ends here - when \n9 matches our future -
9             #now our current pattern space.
9\n10$        
10
10$

이렇게 하면 현재 컨텍스트에서 범위를 시작하고 나중에 시작할 수 있으므로 범위 제어(특별한 시작 및 종료 컨텍스트와 이를 제어하기 위한 추가 일치가 필요하기 때문에 일부 사람들은 직관적이지 않다고 생각할 수 있음)를 전체적으로 더 쉽게 만듭니다.

달리 말하면...

/this_line/,/that_line/command-다음에서 명령 적용 이 줄까지 포함괜찮아

...더 시각적으로 표현할 수 있습니다...

N;/this_line\n/,/\nthat_line/command;D-응용 프로그램 명령은 다음으로 시작합니다.이 줄~까지괜찮아.

\n이는 여러분이 기대하는 만큼 강력합니다. 편집 명령 외에 패턴 공간에 ewline을 넣을 수 있는 다른 방법이 없기 때문입니다.sed(예: N확장)- 또한 여러분이 원할 수 있는 가장 성능이 뛰어난 솔루션 중 하나입니다.

그래서 나는 don의 예시 데이터를 빌렸습니다.

sed '$!N;/^Match User FOO\n/,/\n[[:upper:]]/!P;D' <<\IN
Match User BAZ
    PasswordAuthentication yes
Match User FOO
    ChrootDirectory /srv/www/FOO
    AllowTCPForwarding no
    X11Forwarding no
    ForceCommand internal-sftp
Match User FOO1
    PasswordAuthentication no
Match User FOO2
    PasswordAuthentication yes
IN

...그리고...

sed '$!N;/^Match User FOO\n/,/\n[[:upper:]]/!P;D' <<\IN
Match User FOO1
    PasswordAuthentication no

Match User FOO2
    PasswordAuthentication yes

Match User FOO
    ChrootDirectory /srv/www/FOO
    AllowTCPForwarding no
    X11Forwarding no
    ForceCommand internal-sftp

Match User FOO2
    PasswordAuthentication yes

IN

...인쇄됩니다...

Match User BAZ
    PasswordAuthentication yes
Match User FOO1
    PasswordAuthentication no
Match User FOO2
    PasswordAuthentication yes

...그리고...

Match User FOO1
    PasswordAuthentication no

Match User FOO2
    PasswordAuthentication yes

Match User FOO2
    PasswordAuthentication yes

...각기.

그러나 빈 줄에서는 범위 컨텍스트를 종료하지 않습니다. 블록 뒤의 모든 빈 줄은 작성 중인 블록의 일부로 간주됩니다. 따라서 두 번째 예에서 출력 줄 사이의 공백은 그 앞의 공백입니다. 예를 들면 다음과 같습니다.

sed '$!N;/^Match User FOO\n/,/\n\([[:upper:]].*\)*$/!P;D' <infile >oufile

...이것은 범위 컨텍스트를 파괴하고 대문자로 시작하는 빈 줄로 출력 쓰기를 다시 시작합니다. 또한 다음과 같은 경우가 더욱 일반적이 될 수 있습니다.

sed '$!N;/^Match User FOO\n/,/\n\([^[:blank:]].*\)*$/!P;D' <infile >oufile

...이렇게 하면 빈 줄이나 공백이 아닌 문자로 열린 줄의 범위가 중단됩니다. 모든 경우에 브레이크아웃 패턴은 다시 시작하고 싶은 패턴이지 계속 멈추고 싶은 일련의 패턴 중 마지막 패턴이 아닙니다.

답변4

하지만sed는 가능하다, awk에서 강력하게 만드는 것이 더 쉽습니다. 다음 스크립트는 Match User FOO(또는 대소문자 및 공백의 변형)으로 시작하는 줄을 건너뛰고 Match User다른 줄에서는 건너뛰기를 중지하고 건너뛰지 않은 모든 줄을 인쇄합니다.

awk '
    tolower($1)=="match" && tolower($2) == "user" {skip = $3 == "foo"}
    !skip
'

스크립트가 중단되면 출력을 임시 파일에 쓴 다음 해당 위치로 이동하십시오. 다른 사람이 동시에 파일을 수정하면 데이터가 손실될 수 있습니다.

awk … </etc/sshd_config >/etc/sshd_config.tmp &&
mv /etc/sshd_config.tmp /etc/sshd_config

관련 정보