특정 단어 뒤에 줄이 설정되지 않은 경우에만 줄을 추가하는 방법

특정 단어 뒤에 줄이 설정되지 않은 경우에만 줄을 추가하는 방법

다음 줄을 추가하기 위해 다음 sed cli를 구축했습니다.

force_https_protocol=PROTOCOL_TLSv1_2

라인 뒤 :

[security]

sed 명령줄 인터페이스:

sed  -i '/\[security\]/a force_https_protocol=PROTOCOL_TLSv1_2'  /etc/ambari-agent/conf/ambari-agent.ini

하지만 문제는 - 라인이 force_https_protocol=PROTOCOL_TLSv1_2 이미 뒤에 있을 때입니다.[security]

이미 존재하는 경우 줄 추가를 무시하도록 sed 구문을 어떻게 변경할 수 있습니까?

예상 출력

[security]
force_https_protocol=PROTOCOL_TLSv1_2
keysdir=/var/lib/ambari-agent/keys
server_crt=ca.crt
passphrase_env_var_name=AMBARI_PASSPHRASE

잘못된 파일:

[security]
force_https_protocol=PROTOCOL_TLSv1_2
force_https_protocol=PROTOCOL_TLSv1_2
keysdir=/var/lib/ambari-agent/keys
server_crt=ca.crt
passphrase_env_var_name=AMBARI_PASSPHRASE

답변1

파일의 모든 "force_https_protocol=PROTOCOL_TLSv1_2"가 [security] 태그 내에 있고 다른 곳에 나타나지 않는다고 가정합니다.

sed -e '/^force_https_protocol=PROTOCOL_TLSv1_2$/d'\
    -e '/\[security\]/a force_https_protocol=PROTOCOL_TLSv1_2' file

아이디어는 "force_https_protocol=PROTOCOL_TLSv1_2" 문자열만 포함하는 파일의 모든 줄을 제거하는 것입니다.

설명하다

/^force_https_protocol=PROTOCOL_TLSv1_2$/d'

"force_https_protocol=PROTOCOL_TLSv1_2" 문자열이 포함된 모든 줄을 삭제합니다.

시험

$ cat file
[security]
force_https_protocol=PROTOCOL_TLSv1_2
keysdir=/var/lib/ambari-agent/keys
server_crt=ca.crt
passphrase_env_var_name=AMBARI_PASSPHRASE

[security]
keysdir=/var/lib/ambari-agent/keys
server_crt=ca.crt
passphrase_env_var_name=AMBARI_PASSPHRASE

$ sed -e '/^force_https_protocol=PROTOCOL_TLSv1_2$/d'\
      -e '/\[security\]/a force_https_protocol=PROTOCOL_TLSv1_2' file
[security]
force_https_protocol=PROTOCOL_TLSv1_2
keysdir=/var/lib/ambari-agent/keys
server_crt=ca.crt
passphrase_env_var_name=AMBARI_PASSPHRASE

[security]
force_https_protocol=PROTOCOL_TLSv1_2
keysdir=/var/lib/ambari-agent/keys
server_crt=ca.crt
passphrase_env_var_name=AMBARI_PASSPHRASE

답변2

1. AWK를 사용하세요

보다 일반적인 문제를 추가하는 가능한 해결책은 다음과 같습니다.경우에만아직 나타나지 않았습니다.

간단한 접근 방식은 파일을 뒤로 탐색하여 마지막으로 발생한 시점을 추적하는 것입니다., 특정 라벨이 나타날 때마다(라벨 자체를 인쇄하기 직전) 인쇄하지만, 아직 본 적이 없는 경우에만() 하지만 마주치는 것을 잊어버리세요() 태그를 만날 때마다. 물론 마지막 단계는 결과를 뒤집는 것입니다.

tac file | awk '
    /^force_https_protocol=PROTOCOL_TLSv1_2$/ {
        seen = 1
    }
    /^\[security\]$/ {
        if ( ! seen ) {
            print "force_https_protocol=PROTOCOL_TLSv1_2"
        }
    }
    /^\[[^]]*\]$/ {
        seen = 0
    }
    1' | tac

tac, 포함 된GNU Coreutils, 파일을 한 줄씩 연결하고 역방향으로 만듭니다. U&L의 여러 Q&A에서는 기타/표준 도구(예:명령 sed '1!G;h;$!d' 파일 내용을 어떻게 되돌리나요?그리고역방향 가져오기).

force_https_protocol=PROTOCOL_TLSv1_2다음 텍스트 조각 중 첫 번째 부분 뒤에는 삽입되지 않습니다 .[security]

[security]
keysdir=/var/lib/ambari-agent/keys
force_https_protocol=PROTOCOL_TLSv1_2
passphrase_env_var_name=AMBARI_PASSPHRASE

[security]
...

그냥 삽입하세요라벨이 나타날 때마다이미 존재하는 동일한 접근 방식으로 인해 다음이 발생할 수 있습니다.

tac file | awk '
    /^force_https_protocol=PROTOCOL_TLSv1_2$/ {
        seen = NR
    }
    /^\[security\]$/ {
        if ( ( NR == 1 ) || ! ( NR == seen + 1 ) ) {
            print "force_https_protocol=PROTOCOL_TLSv1_2"
        }
    }
    1' | tac

(이것~ 할 것이다위의 텍스트 예시 뒤에 삽입하세요 force_https_protocol=PROTOCOL_TLSv1_2.)[security]

2. sed를 사용하세요

sed다양한 루프를 사용할 수 있습니다 ( N;P;D;U&L의 다른 Q/A에서 이에 대해 광범위하게 다루고 있습니다. 예:sed를 사용하여 여러 줄 문자열을 바꾸는 방법은 무엇입니까?또는sed를 사용하여 패턴 뒤의 다음 줄을 편집하는 방법은 무엇입니까?).

해당 행은 이전 행이 아직 존재하지 않는 경우 force_https_protocol=PROTOCOL_TLSv1_2에만 으로 구성된 행 뒤에 삽입됩니다.[security]

sed '
  $! {
    N
    P
    /^\[security\]\n/ {
      /\nforce_https_protocol=PROTOCOL_TLSv1_2$/ b b
      i\
force_https_protocol=PROTOCOL_TLSv1_2
    }
    :b
    D
  }
  s/^\[security\]$/&\
force_https_protocol=PROTOCOL_TLSv1_2/'

이 스크립트는 다음과 같습니다.

  • 마지막 줄( )을 제외한 각 줄 에 대해 $!개행 문자와 다음 줄을 패턴 공간( N)(이미 현재 줄이 포함되어 있음)에 추가합니다.
  • P해당 줄이 다음과 같은 경우 패턴 공간( ) 의 첫 번째 줄을 인쇄합니다 [security].
    • ...다음 줄은 입니다 force_https_protocol=PROTOCOL_TLSv1_2. 패턴 공간에서 첫 번째 줄을 제거하고 새 루프( b b, :b D)를 시작하세요.
    • 그렇지 않으면 패턴 공간에서 첫 번째 줄을 제거하고 새 루프를 시작하기 전에 force_https_protocol=PROTOCOL_TLSv1_2표준 출력( )으로 인쇄합니다( ) .i\D
  • 마지막 줄이 이면 [security], 그 줄을 그 자체로 바꾸고 그 뒤에 줄 바꿈을 추가 force_https_protocol=PROTOCOL_TLSv1_2하고 결과를 인쇄합니다(암시적 을 통해 p).

관련 정보