실시예 1

실시예 1

result.txt보여드리기 위해 샘플 텍스트 파일이 있습니다 .

{HEX}.A.Bs
{HEX}.A.Bss
{HEX}.A.Bsss
{HEX}.A.Bssss

그러나 실제 애플리케이션에서는 내용에 result.txt다음과 같은 문자가 한 줄씩 포함될 수 있습니다.

/usr/local/abc.txt
/var/tmp/
png
OIPOP()_+(_)&*#)@IOJDNU*@Utest

Bash 스크립트의 매개변수를 통해 문자열 한 줄을 삭제하고 싶습니다. 따라서 내 bash 스크립트에는 test.sh다음 코드가 있습니다.

!/bin/sh
#test.sh
result=result.txt
del="$1"
sed -i "/$del/d" $result
cat result.txt

실시예 1

따라서 삭제하려면 "{HEX}.A.Bs"매개변수를 사용하여 다음 스크립트를 실행합니다.

./test.sh "{HEX}.A.Bs"

"{HEX}.A.Bs"이렇게 하면 inside라는 문자열이 제거됩니다 .result.txt 하지만 안에 있는 모든 것은 result.txt 삭제되었습니다. 예상되는 출력은 다음과 같아야 합니다.

{HEX}.A.Bss
{HEX}.A.Bsss
{HEX}.A.Bssss

실시예 2

삭제하고 싶은 경우 "{HEX}.A.Bss":

./test.sh "{HEX}.A.Bss"

위의 예문자열 하나만 남기고 "{HEX}.A.Bs" ~에 result.txt. 문자열만 제거해야 합니다 "{HEX}.A.Bss". 따라서 예상되는 결과는 다음과 같습니다.실시예 2다음과 같은 결과가 생성되어야 합니다.

{HEX}.A.Bs
{HEX}.A.Bsss
{HEX}.A.Bssss

여기 코드에 어떤 문제가 있는지 알 수 있나요?

답변1

문자열과 일치하는 줄을 삭제하려면 내부 편집을 위한 GNU awk(GNU sed 와 동일)와 같이 리터럴 문자열을 이해하는 도구를 사용하세요.

del="$1" awk -i inplace '($0"") != ENVIRON["del"]' "$result"

답변2

사용 perl( -i최신 구현에서 지원되는 일부 비표준 옵션은 sed실제로 다음에서 차용되었습니다 perl):

LINE_TO_REMOVE='{HEX}.A.Bs' perl -i -nle '
  print if $_ ne $ENV{LINE_TO_REMOVE}' -- "$file"

사용하려면 sed( sed여기서 GNU 또는 호환 가능하다고 가정) 먼저 필요합니다.일치를 위해 문자열에서 정규식 연산자를 이스케이프하세요.( .예제에 사용된 이스케이프되지 않은 문자를 포함하면 모든 단일 문자와 일치함) 시작과 끝에 ^각각 고정합니다 $.

string='{HEX}.A.Bs'
regexp='^'$(printf '%s\n' "$string" | sed 's:[][\\/.^$*]:\\&:g')'$'
sed -i -e "/$regexp/d" -- "$file"

(또한 $string파일에 유효한 텍스트가 포함되어 있다고 가정합니다).

답변3

코드의 문제는 {HEX}.A.Bss하위 문자열이 성공적으로 일치한다는 것입니다.모든철사.

문자열에 다음이 포함되어 있지 않다고 가정합니다.이스케이프해야 하는 문자, 대신 사용할 수 있습니다

sed "/^$string\$/d" filename

즉, 선의 시작과 끝 부분에 패턴을 고정합니다.

패턴이 생겼을 때부터하다이스케이프해야 하는 문자가 포함되어 있습니다( , 단일 문자와 일치). 를 사용하거나 문자열 비교를 수행하는 것이 .더 안전합니다 .grep -Fawk

을 계속 사용하려면 sed문자열의 모든 점이 점으로 일치하는지 확인하고 그 외에는 일치하지 않는지 확인하세요.

pattern=$( printf '%s\n' "$string" | sed 's/[.]/[.]/g' )
sed "/^$pattern\$/d" filename

문자열과 정확히 일치하는 행을 제거하려면 다음을 사용하십시오.

grep -v -xF -e "$string" filename >newfile && mv newfile filename

여기서 사용되는 옵션 grep

  • -v: 테스트의 의미를 부정합니다(예: 모든 줄).아니요일치하는 패턴이 추출됩니다.
  • -x: 주어진 패턴을 따르려면 전체 라인이 필요합니다.
  • -F: 패턴을 정규식 대신 문자열로 처리합니다.
  • -e: "다음 매개변수는 모드입니다." 값이 $string대시로 시작하는 경우 필수입니다.

원본 파일의 메타데이터(예: 소유권, 권한 등)를 최대한 많이 보존하려면 파일을 복사하고 grep복사본에 작업을 적용한 후 결과를 원본 파일로 리디렉션하세요.

cp filename filename.tmp &&
grep -v -xF -e "$string" filename.tmp >filename
rm -f filename.tmp

답변4

나는 \b이것이 단어 경계에 대한 것이라고 생각하며 줄에 "{HEX}.A.Bs anotherword"or가 포함된 경우 "{HEX}.A.Bs filename"(즉, 문자열에 공백과 파일 이름으로 "filename"이 포함되어 있는 경우)에도 제거됩니다.

따라서 특정 "{HEX}.A.B"만 삭제하려면 다음을 사용하는 것이 좋습니다.

$ sed '|^'"$del"'$|d' $result  

"$del"문자열 사이에 작은따옴표를 넣어 전달하는 문자열을 포함하면 '패턴이 아닌 있는 그대로 정확하게 일치한다는 뜻입니다.

진주:

perl -pe "s|^\Q$del\E$||g;" $result | sed '/^$/d'   

\Q=> 패턴 메타문자를 인용(비활성화)합니다.\E

그 자리에서 편집하려면(파일을 직접 변경/편집) 다음을 사용할 수 있습니다.

$ perl -pe "s|^\Q$del\E$||g;" $result | sed '/^$/d' > tmpfile && mv tmpfile $result  

awk를 사용하려면:

$ awk -v d=$del  '$0 != d' $result > tmp && mv tmp $result

grep을 사용하려면 다음을 수행하십시오.

$grep -vxF "$del" $result > tmp && mv tmp $result

-에프,--fixed-strings, --fixed-regexp는 PATTERN을 고정 문자열 목록으로 해석합니다.
-V,--invert-match 일치하지 않는 행을 선택하려면 일치의 의미를 반전시킵니다. (-v는 POSIX에 의해 지정됩니다.)
-엑스,--line-regexp는 전체 줄과 정확히 일치하는 일치 항목만 선택합니다. (-x는 POSIX에 의해 지정됩니다.)

관련 정보