쉘 *for*는 파일을 반복하고 각 줄마다 sed를 사용하여 다른 파일에서 줄을 삭제합니다.

쉘 *for*는 파일을 반복하고 각 줄마다 sed를 사용하여 다른 파일에서 줄을 삭제합니다.

long-cluttered-filename.txt문자열과 일치하는 줄을 제거하여 정리하려고 합니다 delete-these-lines.txt...

$ cat delete-these-lines.txt
context
platform
server
civicrm
site_enabled
client
redirection
cron_key
^\s*[0-9]*\s
alias
profile
install
ssl_
address

...간단한 for루프를 사용하면 다음과 같이 해당 파일의 줄을 반복할 수 있습니다.

$ for l in delete-these-lines.txt; do cat $l; done
context
platform
server
civicrm
site_enabled
client
redirection
cron_key
^\s*[0-9]*\s
alias
profile
install
ssl_
address

그런데 교체하려고 했더니 잘 cat안되네요 sed. 다음 중 어느 것도 작동하지 않습니다.

for l in delete-these-lines.txt; do sed -i "/$l/d" long-cluttered-filename.txt; done
for l in delete-these-lines.txt; do sed -i '/"$l"/d' long-cluttered-filename.txt; done

$l변수 보간에 문제가 있습니까? 이것이 for루프의 한계입니까?

비슷한 답변을 봤습니다텍스트 파일의 문자열 목록에 제공된 문자열 줄을 제거하기 위해 sed를 반복합니다.그리고파일에서 줄을 읽고 삭제while루프를 사용 read하지만 가능하다면 루프를 사용하는 것을 선호합니다 for. 그렇지 않다면 이유를 알고 싶습니다.

답변1

두 개의 파일이 있고 하나에는 다른 파일에서 제거하려는 문자열 목록이 포함되어 있는 경우 다음과 같은 간단한 작업으로 모든 작업을 수행할 수 있습니다 grep.

grep -v -f delete-these-lines.txt long-cluttered-filename.txt

long-cluttered-filename.txt그러면 의 패턴과 일치하지 않는 모든 문자열이 출력됩니다 delete-these-lines.txt.

long-cluttered-filename.txt의 일부 문자열에 포함된 경우 client(예 123superclient456: ), 여전히 일치하며 client출력에서 ​​제외됩니다.

답변2

변수 이름으로 문자를 사용하지 마십시오. l숫자와 너무 비슷해 1코드가 복잡해지기 때문입니다. 이미 알고 있듯이 하고 싶은 일은 나쁜 생각이지만 보세요.https://mywiki.wooledge.org/DontReadLinesWithFor셸의 파일에서 줄을 읽고 다음과 같이 작성하는 방법을 알아보세요.

while IFS= read -r regexp; do
    sed -i "/$regexp/d" long-cluttered-filename.txt
done < delete-these-lines.txt

그러나 경고를 받은 모든 이유로 인해 그렇게 하지 마십시오(그리고 grep -v -f delete-these-lines.txt long-cluttered-filename.txt > tmp && mv tmp long-cluttered-filename.txt덜 효율적이고 덜 견고하며 덜 이식성 있게 재구현하게 될 것입니다).

관련 정보