sed로 특정 문자열을 포함한 라인 삭제하기

thisrule의 이미지

특정 문자열을 포함한 라인 삭제하려는 대상의 파일이 수백개 있습니다.
vi에서는 :%g/찾을문자열/d 하면 간단히 되는데 이런 파일이 여러개 있으니 당황스럽네요.
sed로 그렇게 할 수 있을거 같은데 잘 안됩니다.
kldp에 있는 sed manual에 문자열 치환은 있는데 라인 삭제는 없네요. :(
아시는 분들의 도움 바랍니다.

flyingykk의 이미지

sed /찾는 문자열/d file 하시면 찾는 문자열을 포함하는 줄을 제외한 나머지 줄만 출력됩니다.

여러 파일에 적용한 후 결과를 새로운 파일에 저장하려면 스크립트 속에서 사용하셔야할 것 같습니다.

하늘하늘이의 이미지

잘 적용했습니다. 감사해요~

oldbell의 이미지

#!/bin/sh 
cd /home/uman/target 
for i in `find . -name "*.txt" -exec grep -l "찾는문자열" {} \;` ; do 
sed /찾는문자열/d $i
done 

이렇게 하면 될라나요?? (돌려보지는 않았습니다. )

인생의 무게를 느껴라. 아는 만큼 보이는게다.

송효진의 이미지

vi 로 하시던거면 vi 로 할 수 있어요.

vi -c "%g/찾을문자열/d" -c "wq" filename

find 랑 연동하면 되겠죠.

thisrule의 이미지

송효진 wrote:
vi 로 하시던거면 vi 로 할 수 있어요.

vi -c "%g/찾을문자열/d" -c "wq" filename

find 랑 연동하면 되겠죠.


파일 하나에 대해선 잘 되는데 여러 파일로 하니깐 잘 안되네요.
vi -c "%g/찾을문자열/d" -c "wq" *.txt
하니깐 첫번째 파일을 잘 되는데 나머지 파일엔 적용되지 않습니다.
그냥 sed로 해보아야 겠습니다.
송효진의 이미지

find 와 연동이요...

find . -type f -name *.txt -exec vi -c "%g/찾을문자열/d" -c "wq" "{}" \;

whitekid의 이미지

송효진 wrote:
find 와 연동이요...

find . -type f -name *.txt -exec vi -c "%g/찾을문자열/d" -c "wq" "{}" \;

find에서 -name에 *을 사용할 경우는 ""로 묶어주는 센스~~

What do you want to eat?

sodomau의 이미지

sed 는 아니지만
grep -v string file
이렇게 하셔도..

thisrule의 이미지

sodomau wrote:
sed 는 아니지만
grep -v string file
이렇게 하셔도..

grep -v option은 해당 파일에서 string이 없는 라인을 찾아주는거 아닌가요?
즉, 원래 grep의 반대동작이요. 좀 착각하신듯...
송효진의 이미지

원하는 목적이 매칭되는 줄을 지우는 것이므로 활용은 되겠네요.
grep -v 매치 file > file.out

문제는 파일을 직접 수정하지는 못하니, 스크립트를 하나 짜야 하는 번거로움이 있겠네요.

thisrule의 이미지

송효진 wrote:
원하는 목적이 매칭되는 줄을 지우는 것이므로 활용은 되겠네요.
grep -v 매치 file > file.out

문제는 파일을 직접 수정하지는 못하니, 스크립트를 하나 짜야 하는 번거로움이 있겠네요.


오! 그렇군요. 제가 착각했네요. :oops:
김도현의 이미지

perl도 괜찮다면

perl -pi -e "s/.*문자열.*//s" *.txt

정도면 어떨까요?

cinsk의 이미지

한 파일에서 특정 문자열이 나오는 줄을 삭제하는 것은 sed(1)의 'd' 명령으로 가능합니다. 예를 들어 "asdf"이 있는 줄을 삭제하는 것은 다음과 같습니다:

$ cat tmp.txt
asdf qwer
qwer zxcv
zxcv asdf
qwer zxcv
asdf asdf
qwer qwer
$ sed -e '/asdf/d' tmp.txt
qwer zxcv
qwer zxcv
qwer qwer
$ _

그러나 sed로 기존 파일을 변경하는 것을 불가능하기 때문에 다음과 같이 script를 작성하면 됩니다 (편의상 tmp.sh라고 합시다):

#!/bin/sh

if test $# -lt 1; then
    echo "usage: $0 [FILE...]"
    exit 1
fi

for f in "$@"; do
    tmpfile="/tmp/remove-$$"
    trap "rm $tmpfile" 1 2 3 15
    sed -e '/asdf/d' "$f" > $tmpfile
    mv $tmpfile "$f"
    trap "" 1 2 3 15
done

그리고 아까 만들어둔 tmp.txt를 t1.txt, t2.txt, t3.txt로 복사했습니다:

$ ls -l tmp.txt
-rw-r--r--  1 cinsk users 60 Jun 20 19:51 tmp.txt
$ cp tmp.txt t1.txt
$ cp tmp.txt t2.txt
$ cp tmp.txt t3.txt
$ ls -l t*.txt
-rw-r--r--  1 cinsk users 60 Jun 20 19:50 t1.txt
-rw-r--r--  1 cinsk users 60 Jun 20 19:50 t2.txt
-rw-r--r--  1 cinsk users 60 Jun 20 19:50 t3.txt
-rw-r--r--  1 cinsk users 60 Jun 20 19:51 tmp.txt
$ _

그리고 나서 주어진 script를 실행하면:

$ ./tmp.sh
usage: ./tmp.sh [FILE...]
$ ./tmp.sh t[1-3].txt
$ ls -l t*.txt
-rw-r--r--  1 cinsk users 30 Jun 20 19:55 t1.txt
-rw-r--r--  1 cinsk users 30 Jun 20 19:55 t2.txt
-rw-r--r--  1 cinsk users 30 Jun 20 19:55 t3.txt
-rw-r--r--  1 cinsk users 60 Jun 20 19:51 tmp.txt
$ cat t1.txt
qwer zxcv
qwer zxcv
qwer qwer
$ _

그럼 이만. :wink:

flyingykk의 이미지

cinsk님의 스크립트에서

1. trap 명령을 쓴 이유
2. sed 출력을 바로 새 파일에 쓰지 않고 $tmpfile에 썼다가 mv하는 이유

가 궁금합니다. $tmpfile을 거치는 것은 보안 때문에 그렇다는 감만 잡고 있지 구체적인 것은 잘 몰라서...

설명하기 귀찮으시면 링크라도 좀...

cinsk의 이미지

보통 filter 형태로 쓰이는 프로그램들은, source를 덮어 쓰게 작업할 수가 없습니다. 따라서, 임시로 다른 파일에 저장한 다음, 그 것을 덮어 쓰는 방법을 주로 씁니다. 요청하신 내용이, 특정 줄을 제거하는 방법이었으므로, 결국 주어진 source에 어떤 가공을 한 다음, 다시 source에 덮어 쓰는 것으로 판단했습니다. 이 경우, redirection을 써서 source를 덮어 쓰게 될 경우, source 자체가 사라질 위험이 있습니다. 즉, 다음과 같은 명령은 상당히 위험합니다.

$ filter_program source > source

따라서 결과를 임시 파일에 저장하고, 그 것을 다시 source로 덮어쓰는 방식을 씁니다:

$ filter_program source > temporary
$ mv temporary source
$ _

그런데, script 실행 도중 break 키를 누른다거나 하는 등의 interrupt가 발생하면, temporary가 만들어진 상태에서 script가 중단될 경우가 있습니다. 이런 경우가 자주 발생하면, 쓸모없는 임시 파일들이 어디엔가 쌓이겠죠. 이 것을 방지하기 위해서, trap 명령을 써서, 중간에 특정 interrupt (signal)가 발생할 경우, script를 끝내기 전에, 강제로 임시 파일을 지우게 만듭니다.

flyingykk의 이미지

cinsk님 답변 감사합니다.

보안 때문이 아니라 원본과 같은 이름을 갖는 출력을 얻기 위한 것이었군요. 만약 원본과 출력이 다른 이름을 갖는다면 다음과 같이 간단하게 할 수 있겠네요.

for f in "$@"; do
    sed -e '/asdf/d' "$f" > "$f.new"
done
익명 사용자의 이미지

sub directory 까지 되려면 어떻게 해야 하나요? recrusive 하게요..

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.