텍스트 파일의 특정 태그/문자열 사이의 텍스트를 바꾸는 bash/sh 스크립트

텍스트 파일의 특정 태그/문자열 사이의 텍스트를 바꾸는 bash/sh 스크립트

/bin/sh 또는 /bin/bash 스크립트를 사용하여 실행될 실행 파일을 생성 중입니다. 이와 같은 구조를 포함하는 파일이 있습니다 . 구성 파일에는 태그 와 태그가
하나만 있습니다. 해당 태그 사이의 텍스트,#start#end

...

#start
FirewallRuleSet global {
    FirewallRule allow tcp to google.com
    FirewallRule allow tcp to facebook.com

#more rules
}
#end

FirewallRuleSet known-users {
    FirewallRule allow to 0.0.0.0/0
}

...

원하는 출력은 다음과 같습니다.

...

#start
FirewallRuleSet global {
    FirewallRule allow tcp to google.com
    FirewallRule deny tcp to facebook.com
    FirewallRule deny tcp to twitter.com
    FirewallRule allow tcp to exaple.com



#more rules
}
#end

FirewallRuleSet known-users {
    FirewallRule allow to 0.0.0.0/0
}

...

#start그 사이의 전체 텍스트를 새로운 텍스트로 바꾸는 방법은 무엇입니까? #end이 프로필에 규칙을 추가하거나 제거하고 싶습니다.

이것은 구성 파일의 일부이며 해당 텍스트에서 허용된 URL을 수정하고 싶습니다.

답변1

사용

sed '/#시작/,/#끝/바꾸기 명령'

예를 들어 파일 이름이 지정되어 myconfig있고 해당 섹션에서 "허용"을 "거부"로 바꾸려면 다음과 같이 말할 수 있습니다.

sed '/#start/,/#end/s/allow/deny/' myconfig

그러면 파일은 변경되지 않고 그대로 유지되며 수정된 파일의 모양이 표준 출력에 표시됩니다. 명령이 올바른지 확인하려면 먼저 이 작업을 수행해야 합니다. 실제로 파일을 변경하려면 다음을 추가하십시오.-i옵션:

sed -i '/#start/,/#end/s/allow/deny/' myconfig

바꾸고 싶다면모두텍스트(모두텍스트) 이 두 줄 사이에 다음과 같은 작업을 수행할 수 있습니다.루카스의 대답:

sed '/#start/,/#end/c\
새 텍스트 줄 1\
새 텍스트 라인 2\
        ︙\
새 텍스트 줄N-1\
새 텍스트 줄N(최종)' ←따옴표를 닫습니다. 여기에는 백슬래시가 없습니다.

c~이다sed(및 ed)의 hange 명령은 "전체 줄 바꾸기"를 의미합니다. 단순히 #start합계 라인을 변경하지 않고 그대로 둘 수는 없습니다 #end. 이를 유지하려면 다시 삽입해야 합니다.

sed -i '/#start/,/#end/c\
#start\
FirewallRuleSet global {\
    FirewallRule allow tcp to google.com\
    FirewallRule deny tcp to facebook.com\
                      ︙                 \
\
#more rules\
}\
#end' myconfig

/#start/,/#end/#start 포함하는 첫 번째 줄부터 포함하는 첫 번째 줄까지 범위를 지정합니다 #end. 이러한 문자열만 포함하고 다른 문자열은 포함하지 않는 줄을 찾으려면 를 사용하세요 /^#start$/,/^#end$/.

답변2

기반으로G맨의 대답그리고 코멘트:

sed -i '/#start/,/#end/ {
//!d
/#start/a\
some new text\
more lines\
end of new text (no backslash here!)
}' myconfig

설명하다:

  1. /#start/,/#end/ { .... }텍스트 "#start"와 "#end"(포함) 사이의 각 줄에서 중괄호로 묶인 명령을 실행합니다. G-Man의 답변을 비교해 보세요.
  2. a추가 명령입니다. 새 텍스트가 추가되도록 "#start"와 일치하는 줄에서만 실행됩니다. 백슬래시+새 줄로 끝나지 않는 줄까지 줄을 추가합니다.

답변3

두 가지 상태, 즉 두 가지 상태 사이를 이동하는 두 가지 서로 다른 존재 라인이 있기 때문에 이것이 awk(또는 Perl 또는 Python)의 작업입니다. 현재 언어는 Python이므로 프로그램은 다음과 같습니다.

import sys

rule_file = sys.argv[1]
new_rules = sys.argv[2]

mode = "save_rules"
for line in open(rule_file):
    line = line.strip()
    if line == "#start":
        print line
        print new_rules
        mode = "replace_rules"
    elif line == "#end":
        mode = "save_rules"
        print line
    elif mode == "save_rules":
        print line

이제 rule_replace.py에 저장하고 호출하세요.

python rule_replace.py my_rule_file.txt 'FirewallRuleSet global {
FirewallRule allow tcp to google.com
FirewallRule deny tcp to facebook.com
FirewallRule deny tcp to twitter.com
FirewallRule allow tcp to exaple.com



#more rules
}' >new_rules.txt

물론 명령줄에 새 규칙을 넣을 필요는 없습니다. 이를 쉘 변수에 넣으면 호출은 다음과 같을 것이라고 가정합니다.

$ python rule_replace.py my_rule_file.txt $new_rules

이 스크립트는 작업하는 동안 프로덕션 환경에 대한 솔루션이 아닙니다. 오류는 포착되지 않습니다(예: 소스 파일이 존재하지 않는 경우). #start 행 뒤에는 항상 #end 행이 따르고 해당 행은 사용자가 설명하는 것과 똑같다는 것을 확인하지 않고 가정합니다. 프로덕션에 투입되면 일부 로깅을 사용할 수도 있습니다.

답변4

G-Man의 답변을 바탕으로 이 작업을 수행하고 사용자 정의 구분 기호 및 변수 대체를 사용하는 방법은 다음과 같습니다(복잡성으로 인해 즉시 명확하지 않음).

주어진 inputfile.txt:

Line1
Line2
<!-- /START_MARKER/ -->
Line4
Line5
Line6
<!-- /END_MARKER/ -->
Line8
Line9

다음 명령/스크립트를 사용하십시오.

customtext="Any kind of variable text here"

sed -i '\%<!-- /START_MARKER/ -->%,\%<!-- /END_MARKER/ -->%c\
foo '"$customtext"' abcxyz whatever' inputfile.txt

결과 :

Line1
Line2
Any kind of variable text here
Line8
Line9

여기서는 많은 일이 일어나고 있으며 아래에 설명되어 있습니다.

'- 모든 항목은 작은따옴표로 묶어야 합니다.

\%- 사용자 정의 구분 기호를 사용하는 경우(예: /마크업에서 다른 구분 기호를 사용해야 하는 경우) 여기에서 이스케이프 처리해야 합니다.

<!-- /START_MARKER/ -->- 텍스트 시작 태그. 이 경우 데모용으로 이상한 예입니다.

%- sed 구분 기호, 이스케이프되지 않음

,- 반점(?)

\%- sed 구분 기호를 다시 사용하세요. 이번에는 이스케이프해야 합니다.

<!-- /END_MARKER/ -->- 텍스트 종료 태그

%c- sed 구분 기호(이스케이프되지 않음) 및c

\- 백슬래시는 다음 텍스트/라인을 대체용으로 사용해야 함을 나타냅니다.

foo- 일부 대체 텍스트

'"$customtext"'- 변수 텍스트를 사용자 정의하고 '변수 "대체를 활성화한 다음 자유 텍스트 모드로 돌아갑니다 ".'

abcxyz whatever- 추가 대체 텍스트

'- 작은따옴표 끝

inputfile.txt- 파일 이름

관련 정보