sed 명령을 사용하는 동안 패턴으로 변수를 전달하는 방법은 무엇입니까?

sed 명령을 사용하는 동안 패턴으로 변수를 전달하는 방법은 무엇입니까?

파일이 있습니다abc.sh

search_dir='dummy'
filename='numbers.txt'

for entry in "$search_dir"/*
do
  while read p;
  do 
    sed -i '' "/$p/d" $entry
  done < $filename
done

패턴이 일치하는 행을 삭제해 보세요. 기본적으로 패턴은 파일에서 전달하는 문자열일 뿐입니다. 그러나 불행히도 작동하지 않습니다.

내가 디버깅할 수 있었던 것은 올바른 모드에서 변수를 전달하지 않았다는 것입니다.

편집하다: 숫자.txt

2018061300006178
2018061300006179
2018061300006325
2018061300006326
2018061400006505

search_dir에 있는 파일의 내용은 다음과 같습니다.

1888~2018061400006505~0101~1~OWNED~SELF EMPLOYED~~~~3~~AGRICULTURE~~~OTHERS~AGRICULTURIST~~~AGRICULTURE~~~~~~~~N~N~Y~N~N~~300000-500000~~~49582E95361D5FA0C10C4C419B2940591C17E94EF329C31047A6B7DE26E68638
1889~2018061400006505~0101~2~OWNED~SELF EMPLOYED~~~~32~~AGRICULTURE~~~OTHERS~AGRIC

그래서 Numbers.txt에는 2018061400006505가 포함되어 있고 파일에는 숫자 관련 데이터도 포함되어 있으므로 주어진 숫자와 일치하는 줄을 삭제하고 싶습니다.

답변1

sed예제의 숫자에 사용 중인 구분 기호(기본값 /) 가 포함되어 있지 않은 한 $p코드의 는 정규식(모든 의미 포함)으로 해석됩니다.

귀하의 코드:

search_dir='dummy'
filename='numbers.txt'

for entry in "$search_dir"/*
do
  while read p;
  do 
    sed -i '' "/$p/d" $entry
  done < $filename
done

$search_dir여기서는 숫자가 포함된 파일의 모든 줄을 삭제하려고 합니다 $filename. 이것이 효과가 있는지 여부는 치료 sed방법 에 따라 다릅니다 -i ''. 일부 구현의 경우 인수 없이 사용해야 sed합니다 .-i

관련성 sed -i및 이식성:sed -i(제자리에서 편집)를 사용하여 이식성을 달성하는 방법은 무엇입니까?

결과를 임시 파일에 쓴 다음 해당 파일을 원래 파일 이름으로 이동하는 것이 더 안전합니다.

for entry in "$search_dir"/*
do
  while read p;
  do 
    sed "/$p/d" "$entry" >"$entry.tmp" && mv "$entry.tmp" "$entry"
  done <"$filename"
done

이렇게 하면 sed어떤 구현을 사용하더라도 올바르게 작동할 수 있습니다. 일반적으로 말해서, 스크립트를 테스트할 때 파일을 내부적으로 변경하려고 시도하는 것은 좋지 않으므로 mv스크립트가 다른 방식으로 작동하는 방식에 익숙해질 때까지 이를 주석 처리하는 것이 좋습니다.

일반적인 솔루션으로서 이것은 본질적으로 "데이터를 코드로 사용"하기 때문에 여전히 약간 안전하지 않습니다(숫자는 데이터이고 이를 sed스크립트의 일부로 사용하고 있음). 즉, 숫자 파일의 숫자에 을 삽입하기 sed만 하면 스크립트에서 구문 오류가 쉽게 발생할 수 있습니다./

작업이 매우 간단하므로 대신 를 사용할 수 있습니다 grep. 이렇게 하면 내부 while루프도 제거됩니다.

for entry in "$search_dir"/*
do
  grep -Fv -f "$filename" "$entry" >"$entry.tmp" && mv "$entry.tmp" "$entry"
done

그러면 grep해당 패턴이 파일에서 읽혀지고 파일 $filename에 적용됩니다 . 패턴이 포함된 줄은 모두 삭제 합니다 .$entry-v-Fgrep아니요숫자를 정규식으로 해석하지만 고정 문자열로는 해석하지 않습니다. -f "$filename"우리는 grep그것으로부터 $filename.

아래 디렉터리가 있을 수 있는 경우 $search_dir다음 디렉터리를 건너뛰고 싶습니다.

for entry in "$search_dir"/*
do
  [ ! -f "$entry" ] && continue
  grep -Fv -f "$filename" "$entry" >"$entry.tmp" && mv "$entry.tmp" "$entry"
done

또 다른 안전한 방법은 위의 내용 과 해결 방법 awk으로 인해 숫자가 일치하는 것입니다.sedgrep어딘가에행 측면에서 보면 잘못된 행을 삭제할 수도 있습니다. 데이터에서 두 번째로 구분된 필드를 awk쉽게 일치시킬 수 있습니다 .~

for entry in "$search_dir"/*; do
    [ ! -f "$entry" ] && continue
    awk -F '~' 'NR==FNR { num[$0]; next } !($2 in num)' "$filename" "$entry" >"$entry.tmp" &&
    mv "$entry.tmp" "$entry"
done

프로그램 awk은 먼저 숫자를 키로 사용하여 연관 배열/해시를 채운 다음 두 번째 구분 열이 해당 해시의 키가 아닌 $entry파일의 각 행을 인쇄합니다.~

관련 정보