#!/bin/bash
search_string="\/sbin\/iptables -A INPUT -p tcp --dport 12443 -j ACCEPT";
delimeters=$(cat /root/firewall/firewall.txt);
sed -i "s/$search_string/$delimeters$search_string/" /root/result.txt
변수에 /root/firewall/firewall.txt
저장된 줄 앞에 파일 내용을 추가하고 싶습니다 ./root/result.txt
search_string
위의 줄을 포함 하면 /root/firewall/firewall.txt
스크립트가 작동합니다. 그러나 Firewall.txt에 여러 줄이 포함되어 있으면 스크립트는 다음과 같이 중단됩니다.
sed: -e expression #1, char 64: unterminated `s' command
제 생각에는 개행 문자가 문제를 일으키는 것 같은데 제대로 백슬래시할 수 없습니다.
search_string="\/sbin\/iptables -A INPUT -p tcp --dport 12443 -j ACCEPT";
delimeters=$(cat /root/firewall/firewall.txt);
replaced= "$delimeters" | sed -r 's/\\n/\\\\n/g'
sed -i "s/$search_string/$replaced$search_string/" /root/result.txt
이 문제를 어떻게 해결할 수 있나요?
답변1
(이것은 다른 답변과 일부 중복됩니다.)
조금 혼란스러워요. 당신은 말한다,
파일의 내용을 파일
firewall.txt
에 추가하고 싶습니다.result.txt
앞으로한 줄변수 에 저장합니다search_string
.우선, 문제의 중요한 부분이 아닌 경우 전체 경로 이름(
/root/…
)은 문제를 복잡하게 만들고 아무 가치도 없게 됩니다. 간단한 파일 이름을 사용하세요. 결국 로컬 디렉터리에서 디버그해줬으면 좋겠는데,아니요루트로 실행하십시오.둘째, 뭐예몇 가지 예시 데이터를 제공하는 것이 유용할 것입니다. 실제 파일에 실제로 있는 2000줄이 아니라 몇 줄입니다. (다시 말하지만, 테스트 파일에서 이것을 디버깅하고 있는 거죠, 그렇죠?) 예를 들어
result.txt
,One, two, /sbin/iptables -A INPUT -p tcp --dport 12443 -j ACCEPT Buckle my shoe.
그리고
firewall.txt
포함Humpty Dumpty sat on a wall.
당신은 말한다,
firewall.txt
한 줄만 포함하면 스크립트 는#!/bin/bash search_string="\/sbin\/iptables -A INPUT -p tcp --dport 12443 -j ACCEPT"; delimeters=$(cat /root/firewall/firewall.txt); sed -i "s/$search_string/$delimeters$search_string/" /root/result.txt
일하다.
(그런데 줄 끝에 세미콜론은 필요하지 않으며 "구분 기호"라는 단어는 중간에 "limit"이라는 단어와 함께 철자됩니다.) 음, 위의 결과는 다음과 같습니다.
One, two, Humpty Dumpty sat on a wall./sbin/iptables -A INPUT -p tcp --dport 12443 -j ACCEPT Buckle my shoe.
예저것그것이 정말로 당신이 원하는 것인가요? "[a] 파일에 [텍스트]를 추가한다고 말하면 대부분의 사람들은 그렇게 생각하지 않습니다.앞으로한 줄", 특히 두 줄 이상의 텍스트를 삽입하는 것에 대해 이야기하기 시작할 때, 특히 에서처럼 줄바꿈이 계속 있어야 한다고 말할 때 그렇습니다
firewall.txt
. 나는 당신이 정말로 원하는 것이라고 가정합니다.One, two, Humpty Dumpty sat on a wall. /sbin/iptables -A INPUT -p tcp --dport 12443 -j ACCEPT Buckle my shoe.
파일의 마지막 줄을
firewall.txt
이/sbin/iptables
줄과 연결하려면 원하는 내용을 더 정확하게 설명해주세요.당신은 말한다,
search_string="\/sbin\/iptables -A INPUT -p tcp --dport 12443 -j ACCEPT"; delimeters=$(cat /root/firewall/firewall.txt); replaced= "$delimeters" | sed -r 's/\\n/\\\\n/g' sed -i "s/$search_string/$replaced$search_string/" /root/result.txt
글쎄요, 그건 헛소리입니다. 세 번째 줄은 이렇게 대답합니다.
-bash: Humpty Dumpty sat on a wall.: command not found
아마도 당신 말은
교체 =$(에코"$ 구분 기호" | sed -r 's/\\n/\\\\n/g')
?
글쎄, 네가 말했어도
replaced=$(echo "$delimeters" | sed -r 's/\\n/\\\\n/g')
sed
일반적으로 한 번에 한 줄씩 실행하고 개행 문자를 줄의 문자로 처리하지 않기 때문에 아무 소용이 없습니다 (입력이 여러 줄 값을 가진 쉘 변수에서 나온 경우에도 마찬가지입니다. 이는 다음과 다르지 않습니다. 여러 줄 파일). 그것은 무엇을 하는가(제거쓸모없는 사용cat
) 예replaced=$(sed 's/$/\\/' firewall.txt) sed "s/$search_string/$replaced $search_string/" result.txt
를 사용하여
sed 's/$/\\/'
각 줄 끝에 백슬래시를 추가합니다firewall.txt
. 명령 대체가 수행되면 마지막 개행 문자가 제거되므로 그 뒤에 개행 문자( Enter) 를 입력해야 합니다 . 그리고 단순화를 위해 명령을 동일하게 유지하려면 최종 명령을 다음으로 변경하는 것이 좋습니다.$replaced
replaced=$(…)
/sbin/iptables
sed "s/$search_string/$replaced &/" result.txt
대체 문자열에 사용한다는 것은
&
"검색 문자열(정규식)로 찾은 텍스트를 여기에 삽입"한다는 의미입니다.이
s
명령을 사용하면 전체 줄을 삽입할 수 있지만 실제로는 이것이 목적이 아닙니다.a
,i
및 명령c
은 명령 문자열에서 하나 이상의 행을 삽입하는 데 사용됩니다. 그러나 삽입한 텍스트는 파일에서 가져온 것이므로 보기r
(아르 자형ead) 명령. 첫 번째 컷으로,sed "/$search_string/r firewall.txt" result.txt
당신이 원하는 것을 거의 할 것입니다. 거의. 불행하게도
firewall.txt
해당 줄 뒤에 파일 내용을 삽입합니다/sbin/iptables
. 해결 방법(firewall.txt
줄 앞의 내용을 가져오는 방법)을 찾을 수 있었지만/sbin/iptables
매우 복잡합니다.sed -n -e "/$search_string/{s/^/+/; h; r firewall.txt n}" -e 'x; s/^+//p; s/.*//; x; p' result.txt
분명히 파일 이름을 끝내는 구분 문자가
sed
인식되지 않으므로 이라고 말할 때는 을 입력해야 합니다 .;
r firewall.txt
Enter여기 있습니다:
-n
p
: 또는 명령으로 명령하지 않는 한 출력을 쓰지 마십시오r
./$search_string/{…}
$search_string
: ( ) 와 일치하는 각 행에 대해/sbin/iptables …
다음을 수행합니다.s/^/+/
: 줄 시작 부분에+
(create)를 삽입합니다 .+/sbin/iptables …
그러면 행이 검색 문자열과 일치하는 것으로 표시됩니다. (나는 이것에 대해 다시 돌아올 것이다.)h
:+/sbin/iptables …
패턴 공간( )을 예약된 공간에 복사합니다.r firewall.txt
:firewall.txt
파일을 읽고 내용을 씁니다.n
: 이 줄 처리를 중지하고 다음 줄을 읽습니다.
- 그러면 매다른라인(그아니요match
$search_string
) 다음을 수행합니다.x
: 홀드 공간과 패턴 공간의 내용을 교환합니다. 즉, 방금 읽은 줄(아니요match$search_string
)를 저장 공간에 복사한 다음 이전에 저장한 라인(+/sbin/iptables …
공백일 수도 있음)을 패턴 공간에 복사합니다.s/^+//p
: 행이 검색 문자열과 저장된 일치인 경우(즉,신고됨) 을 포함하는 줄+/sbin/iptables …
,+
나머지 부분을 제거하고 인쇄합니다. 그렇지 않으면 아무것도 인쇄되지 않습니다.s/.*//
: 줄을 지웁니다(모든 것을 아무것도 아닌 것으로 바꿉니다). 원래 하고 싶었는데d
(디elete) 여기에 있지만 현재 행의 처리가 종료됩니다.x
: 홀드 공간과 패턴 공간의 내용을 다시 교환합니다. 빈 줄을 패턴 공간에서 예약된 공간으로 이동하고result.txt
방금 배치한 줄을 검색합니다. 마침내…p
: 에서 라인을 인쇄합니다result.txt
.
요컨대,
$search_string
일치하는 줄 (예: ) 을 찾으면/sbin/iptables …
이를 인쇄하지 않고 예약된 공간에 저장하고 파일을 읽고 인쇄합니다firewall.txt
.- 일치하지 않는 다른 모든 행에 대해 저장된 행(있는 경우)을 예약된 공간에서 가져와 인쇄한 다음 현재 행을 인쇄합니다.
아! 마지막 행에서 발생하면
/sbin/iptables …
예약된 공간에 보관되어 있지만 추출을 트리거할 일치하지 않는 후속 행이 없기 때문에 실패합니다./sbin/iptables …
따라서 마지막 행에 더미 행을 추가한 다음 전략적으로 제거하여 마지막 행에서 이런 일이 발생하지 않도록 합시다.echo >> result.txt sed -n -e "/$search_string/{s/^/+/; h; r firewall.txt n}" -e 'x; s/^+//p; $d; s/.*//; x; p' result.txt
이로
$d
인해 마지막 행이 삭제됩니다. (우리는$q
동일한 효과를 사용하고 얻을 수 있습니다.)행이 여러 개인 경우에도 작동합니다
iptables
. 하지만 네, 조금 혼란스러워지고 있습니다. 이제 그 대답은 그다지 나쁘지 않은 것 같습니다.sed "s/$search_string/$replacednewline&/"
답변2
일부 미용 체조에서는 이것이 가능할 수도 있지만 sed
다른 도구를 사용하겠습니다. Perl을 예로 들어 보겠습니다.
search_string="\/sbin\/iptables -A INPUT -p tcp --dport 12443 -j ACCEPT";
delimeters=$(cat /root/firewall/firewall.txt);
perl -i -pe "s/$search_string/$delimeters$search_string/" /root/result.txt
답변3
sed에는 더 많은 명령이 있습니다 . 다른 파일을 현재 스트림으로 읽어들이는 s///
명령이 있습니다 . r
그러나 파일을 읽는 중뒤쪽에현재 행을 배치하려는 경우앞으로현재 라인이므로 약간의 조정이 필요합니다. 검색 문자열에서 슬래시를 이스케이프 처리할 필요는 없으며 sed에서 대체 구분 기호를 사용할 수 있습니다.
$ cat result.txt
foo
bar
/sbin/iptables -A INPUT -p tcp --dport 12443 -j ACCEPT
baz
$ cat firewall.txt
firewall line 1
firewall line 2
$ search_string="/sbin/iptables -A INPUT -p tcp --dport 12443 -j ACCEPT"
$ sed "\%${search_string}% {
# we have hit the search string:
x # move the current line to hold space
r firewall.txt # queue the file for reading
N # append the next line from results
# -> this triggers the actual file read and printing
s/\n// # the "x" command left behind a blank line so we remove it
H # append the current line to the hold space
g # then bring the hold space to the pattern space
}" result.txt
foo
bar
firewall line 1
firewall line 2
/sbin/iptables -A INPUT -p tcp --dport 12443 -j ACCEPT
baz
sed 명령은 다음과 같이 줄일 수 있습니다.
sed "\#${search_string}#{x;r firewall.txt
N;s/\n//;H;g}" result.txt
GNU sed는 파일 이름 뒤에 개행 문자가 필요한 것 같습니다.
답변4
sed '/\-A INPUT -s 192.168.0.0\/24 -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT/a CLIENTSCRIPT2="hello.sh"' file.txt
이 경우 -A INPUT...etc 아래의 file.txt에 변수 CLIENTSCRIPT2="hello.sh"'를 추가했습니다. 구문에서 백슬래시가 이스케이프된다는 점에 유의하세요.