Sed를 사용하여 파일 텍스트 추가

Sed를 사용하여 파일 텍스트 추가
#!/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.txtsearch_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

(이것은 다른 답변과 일부 중복됩니다.)

  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줄과 연결하려면 원하는 내용을 더 정확하게 설명해주세요.

  2. 당신은 말한다,

    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')

    ?

  3. 글쎄, 네가 말했어도

    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) 를 입력해야 합니다 . 그리고 단순화를 위해 명령을 동일하게 유지하려면 최종 명령을 다음으로 변경하는 것이 좋습니다.$replacedreplaced=$(…)/sbin/iptables

    sed "s/$search_string/$replaced
    &/" result.txt
    

    대체 문자열에 사용한다는 것은 &"검색 문자열(정규식)로 찾은 텍스트를 여기에 삽입"한다는 의미입니다.

  4. 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.txtEnter

    여기 있습니다:

    • -np: 또는 명령으로 명령하지 않는 한 출력을 쓰지 마십시오 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"'를 추가했습니다. 구문에서 백슬래시가 이스케이프된다는 점에 유의하세요.

관련 정보