sed를 사용하여 목록 변수에서 행 제거

sed를 사용하여 목록 변수에서 행 제거

목록에서 단어가 포함된 줄을 삭제하기 위해 루프에서 sed를 사용하는 스크립트가 있습니다.

for i in $list; do
  sed -i "/$i/d" file
done

$listSQL 쿼리에서 생성됨:

list=$(psql -d dbname -t -c "SELECT foo from table ORDER BY column DESC")

문제는 우리 회사가 최근 전체 fchown또는 fchmod시스템 호출을 포함하는 더 엄격한 감사 규칙을 구현했다는 것입니다. 를 사용하면 각각 및 시스템 호출이 포함되어 있음 strace을 알 수 있습니다 .sed -ifchownfchmod

큰 목록 변수를 사용하면 iowait이 스파이크가 극적으로 증가하고 auditd가 로그에 엄청난 수의 행을 기록하기 때문에 시스템이 실제로 정체됩니다.

파일이 한 번만 열리고 닫히도록 목록 변수를 한 줄로 sed에 전달하는 방법이 있는지 알아 내려고합니다.

제가 요청했는데 auditd 규칙을 변경할 수 없습니다.

감사해요.

답변1

수많은 인라인 명령을 하나씩 호출하는 대신 한 번만 실행하고 sed단일 스크립트를 사용 하면 됩니다.sed

sedscript=$(mktemp)
for i in $list; do
  echo "/$i/d" >> "$sedscript"
done
sed -f "$sedscript" -i /path/to/file
rm -f "$sedscript"

답변2

의 단어를 주의 깊게 할당할 수 있다면 listbash 매개변수 확장을 사용하여 각 공백을 정규식 대체자로 대체한 |다음 grep해당 작업을 수행하도록 요청할 수 있습니다.

list='auditd the to'
cp file temp &&  
grep -Ev "${list// /|}" temp > file && 
rm temp 

답변3

쉘이 배열을 지원하는 경우 다음을 수행할 수 있습니다.

mapfile -t arr < <(psql -d dbname -t -c "SELECT foo from table ORDER BY column DESC")

명령의 출력을 쉘 배열에 넣은 다음

printf '/%s/d\n' "${arr[@]}" | sed -i.bak -f - somefile

somefile적절한 위치 에 삭제 순서를 적용합니다 . 명령 에서 psql반환된 필드 에 sed.

이는 임시 스크립트 파일을 피하고 필요한 경우 테이블 필드의 공백을 처리해야 한다는 점을 제외하면 @DopeGhoti의 솔루션과 유사합니다.

답변4

이것이 psql -d dbname -t -c "SELECT foo from table ORDER BY column DESC"공백으로 구분된 단어 목록을 제공하는 경우 다음을 시도하십시오.

$ psql -d dbname -t -c "SELECT foo from table ORDER BY column DESC" \
| awk -v FS=" " -v OFS="|" '{$1=$1; print "("$0")"}' \
| xargs -I {} sed -i -E '/{}/d' file

관련 정보