/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
설명하다:
/#start/,/#end/ { .... }
텍스트 "#start"와 "#end"(포함) 사이의 각 줄에서 중괄호로 묶인 명령을 실행합니다. G-Man의 답변을 비교해 보세요.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
- 파일 이름