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 -F
awk
을 계속 사용하려면 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에 의해 지정됩니다.)