원본 텍스트에서 제거하고 싶은 줄이 포함된 텍스트가 있습니다.
예로서
원래의
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