sed: 파일 세트에서 경로 목록 삭제

sed: 파일 세트에서 경로 목록 삭제

이름이 파일이에요공통.txt절대 경로 목록이 포함되어 있습니다. 예를 들어:

/etc
/etc/group
/var/log/syslog

나에게도 파일 세트가 있다<호스트 이름>.txt여기에는 절대 경로 목록도 포함됩니다. 여기에 예가 있습니다.호스트1.txt):

/root/.bashrc
/var/log/syslog
/etc/hosts
/bin/true
/etc
/sbin/rtmon
/etc/group

다음에 나타나는 모든 경로를 제거하고 싶습니다.공통.txt파일 세트의 모든 파일에서<파일 이름>.txt. 그럼 예제 파일은호스트1.txt위의 내용은 다음과 같습니다.

/root/.bashrc
/etc/hosts
/bin/true
/sbin/rtmon

이를 위해 다음 Bash 스크립트를 작성했습니다.

#!/bin/bash

set -o nounset
set -o errexit
set -o pipefail

while read -r ONE_PATH
do
   for ONE_FILE in host1.txt host2.txt host3.txt
   do
      sed -i '\:'"$ONE_PATH"':d' "$ONE_FILE"
   done
done < common.txt

sed 명령을 올바르게 실행하는 데 어려움을 겪고 있습니다. 위에 표시된 결과는 모든 파일이 비어 있을 때 작동됩니다.

목표를 달성하려면 이 문제를 어떻게 해결해야 합니까?

답변1

#!/bin/bash

set -o nounset
set -o errexit
set -o pipefail

declare -r SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
declare -r FILES_DIR=${SCRIPT_DIR%/*}

while read -r ONE_PATH
do
   for ONE_FILE in $(find "$FILES_DIR" -maxdepth 1 -type f -print)
   do
      if [[ "$ONE_FILE" == *".swp" ]] ||
         [[ "$ONE_FILE" == *"common.txt" ]]; then
         continue
      fi

      sed -i '\|^'"$ONE_PATH"'$|d' "$ONE_FILE"
   done

echo "Done removing $ONE_PATH"
done < "$SCRIPT_DIR"/../common.txt

exit 0

답변2

sed를 사용하지 않는 솔루션을 제안해도 될까요?

sort common.txt > common.txt.sorted
for f in host1.txt host2.txt host3.txt ; do
    sort $f > $f.sorted
    diff common.txt.sorted $f.sorted | egrep '^>' | sed -e 's/^> //' > $f.output
    rm $f.sorted
done

종류목록을 알파벳순으로 정렬합니다. 차이점파일과 파일의 차이점을 찾습니다.공통.txt.egrep로 시작하는 줄을 선택합니다 >.host1.txt.sorted하지만 안에는 없어common.txt.sorted. 마지막으로,sed다음에 의해 추가된 선행 >(> 뒤에 공백이 있음)을 제거합니다.차이점.

출력 목록도 알파벳순으로 정렬됩니다.

답변3

먼저 입력을 역순으로 정렬해야 합니다. /etc를 제거한 다음 /etc/group을 찾아보는 것은 소용이 없습니다. 그런 다음 파일에 쓸 수 있는지 확인합니다(건너뛰지 않을 경우). 그런 다음 ONE_PATH를 이스케이프해야 하며 sed가 작업을 수행할 수 있습니다.

sort -r common.txt \
| while read -r ONE_PATH
do
   for ONE_FILE in host1.txt host2.txt host3.txt
   do
      if [ -w "$ONE_FILE" ]
      then
        # sed -i '\:'"$ONE_PATH"':d' "$ONE_FILE"
        ONE_PATH_ESC=$(echo "$ONE_PATH" | sed "s!/!\\\/!g")
        sed -i 's/^'"$ONE_PATH_ESC"'//' "$ONE_FILE"
      fi
   done
done

제공된 테스트 데이터를 사용하면 다음을 얻을 수 있습니다.

$ pr -n host1.txt
1   /root/.bashrc
2
3   /hosts
4   /bin/true
5
6   /sbin/rtmon
7

3개의 빈 줄이 있습니다.

관련 정보