file2에서 file1의 줄 삭제

file2에서 file1의 줄 삭제

원본 텍스트에서 제거하고 싶은 줄이 포함된 텍스트가 있습니다.

예로서

원래의

11
111111111111111111,111111111,11
12,12
99999999999999999,19,1999,199

텍스트에는 삭제할 줄이 포함되어 있습니다.

12,12
99999999999999999,19,1999,199

예상 출력

11
111111111111111111,111111111,11

그렇다면 이 상황에 대한 최선의 해결책은 무엇입니까?

답변1

한 줄의 awk 코드를 사용하여 위의 결과를 얻었습니다.

$ cat file1
11
111111111111111111,111111111,11
12,12
99999999999999999,19,1999,199
$ cat file2
12,12
99999999999999999,19,1999,199

다음 명령은 file1에서 file2의 내용을 삭제합니다.

awk 'NR==FNR {a[$1];next}!($1 in a ) {print $1}' file2 file1

산출:

11
111111111111111111,111111111,11

답변2

다음은 단일 회선 사용자입니다 grep.

grep -Fxv -f file1.txt file2.txt

이 명령은 file1.txt포함되지 않은 행을 나타나는 순서대로 인쇄합니다.file2.txt

순서 유지에 관심이 없다면 다음 comm명령을 사용할 수도 있습니다.

comm -23 <(sort file1.txt) <(sort file2.txt)

이 명령은 정렬된 순서가 file1.txt아닌 행을 출력합니다.file2.txt

또한 while 루프를 사용하여 첫 번째 파일(예: )의 행을 반복하고 , file1.txt두 번째 파일(예: )과 file2.txt각 행을 비교하여 grep찾을 수 없는 경우 해당 행을 인쇄할 수 있습니다. 이렇게 하면 file1.txt삭제된 텍스트 줄을 포함하는 효과가 있습니다 file1.txt. 다음과 같이 보일 수 있습니다:

while read line; do
    if ! grep -qF -- "${line}" file2.txt; then
        echo "${line}";
    fi;
done < file1.txt

결과를 파일에 쓰려면 출력 리디렉션을 사용할 수 있습니다. 예를 들면 다음과 같습니다.

while read line; do
    if ! grep -qF -- "${line}" file2.txt; then
        echo "${line}";
    fi;
done < file1.txt > output.txt

grep명령도 마찬가지입니다 comm.

grep -Fxv -f file1.txt file2.txt > output.txt
comm -23 <(sort file1.txt) <(sort file2.txt) > output.txt

노트:file1.txt출력 리디렉션이 구현되는 방식으로 인해 출력을 다시 리디렉션할 수 없습니다 file1.txt. 이 문제에 대한 자세한 내용은 다음 게시물을 참조하세요.

원본 파일을 바꾸려면 다음과 같이 출력 파일로 덮어쓸 수 있습니다.

mv output.txt file1.txt

스크립트로 변환할 수도 있습니다. 다음은 while 루프를 사용하는 스크립트입니다.

#!/usr/bin/env bash
# removelines.sh

# Set filenames
INPUTFILE="$1"
FILTERFILE="$2"
OUTPUTFILE="$(mktemp)"

# Write the lines from INPUTFILE to OUTPUTFILE
# minus the lines from FILTERFILE
while read line; do
    if ! grep -qF -- "${line}" "${FILTERFILE}"; then
        echo "${line}";
    fi;
done < "${INPUTFILE}" > "${OUTPUTFILE}"

# Replace INPUTFILE with OUTPUTFILE
mv "${OUTPUTFILE}" "${INPUTFILE}"

이것은 동일한 스크립트를 사용하고 있습니다 comm.

#!/usr/bin/env bash
# removelines.sh

# Set filenames
INPUTFILE="$1"
FILTERFILE="$2"
OUTPUTFILE="$(mktemp)"

# Write the lines from INPUTFILE to OUTPUTFILE
# minus the lines from FILTERFILE
comm -23 <(sort "${INPUTFILE}") <(sort "${FILTERFILE}") > "${OUTPUTFILE}"

# Replace INPUTFILE with OUTPUTFILE
mv "${OUTPUTFILE}"

mktemp출력 파일에 대한 임의의 파일 이름을 생성하기 위해 이 함수를 사용한다는 점에 유의하세요 .

스크립트가 실행될 때 실제로 나타나는 모습은 다음과 같습니다.

user@host:~$ cat <<HEREDOC > file1.txt
11
111111111111111111,111111111,11
12,12
99999999999999999,19,1999,199
HEREDOC

user@host:~$ cat <<HEREDOC > file2.txt
12,12
99999999999999999,19,1999,199
HEREDOC

user@host:~$ bash removelines.sh file1.txt file2.txt

user@host:~$ cat file1.txt
11
111111111111111111,111111111,11

관련 정보