programing

Bash의 파일에서 마지막 줄 제거

easyjava 2023. 5. 4. 20:42
반응형

Bash의 파일에서 마지막 줄 제거

파일이 있어요foo.txt다음 행을 포함합니다.

a
b
c

다음과 같은 내용을 얻을 수 있는 간단한 명령을 원합니다.foo.txt존재:

a
b

사용:

sed -i '$ d' foo.txt

-i옵션이 존재하지 않습니다.GNU sed3.95 이전 버전이므로 임시 파일이 있는 필터로 사용해야 합니다.

cp foo.txt foo.txt.tmp
sed '$ d' foo.txt.tmp > foo.txt
rm -f foo.txt.tmp

물론, 그런 경우에는 당신도 사용할 수 있습니다.head -n -1대신에sed.

MacOS:

Mac OS X(10.7.4 기준)의 경우,sed -i위의 명령어는

sed -i '' -e '$ d' foo.txt

이것은 특히 대용량 파일에서 가장 빠르고 간단한 솔루션입니다.

head -n -1 foo.txt > temp.txt ; mv temp.txt foo.txt

맨 위 줄을 삭제하려면 다음을 사용합니다.

tail -n +2 foo.txt

즉, 라인 2에서 시작하는 출력 라인입니다.

사용 안 함sed파일의 맨 위 또는 맨 아래에서 행을 삭제하는 경우 파일이 크면 매우 느립니다.

대용량 파일의 경우

거대한 파일(~300Gb)로 작업 중이었는데 확장된 솔루션이 하나도 없었기 때문에 여기에 있는 모든 답변에 어려움을 겪었습니다.제 솔루션은 다음과 같습니다.

filename="example.txt"

file_size="$(stat --format=%s "$filename")"
trim_count="$(tail -n1 "$filename" | wc -c)"
end_position="$(echo "$file_size - $trim_count" | bc)"

dd if=/dev/null of="$filename" bs=1 seek="$end_position"

또는 하나의 라이너로서:

dd if=/dev/null of=<filename> bs=1 seek=$(echo $(stat --format=%s <filename> ) - $( tail -n1 <filename> | wc -c) | bc )

말로 하면:마지막으로 사용할 파일의 길이를 확인합니다(파일 길이에서 마지막 줄의 길이를 뺀 값).bc), 그리고 그 위치를 파일의 끝으로 설정합니다.dd의 1바이트에서/dev/null그 위에).

이것은 빠릅니다 왜냐하면tail끝부터 읽기 시작하고,dd파일의 모든 줄을 복사(및 구문 분석)하는 대신 파일을 덮어씁니다. 이는 다른 솔루션이 수행하는 작업입니다.

참고: 이렇게 하면 파일에서 줄이 제거됩니다!자신의 파일을 사용해 보기 전에 더미 파일에 백업 또는 테스트를 수행하십시오!

전체 파일을 읽거나 아무것도 다시 쓰지 않고 파일에서 마지막 줄을 제거하려면 다음을 사용합니다.

tail -n 1 "$file" | wc -c | xargs -I {} truncate "$file" -s -{}

마지막 줄을 제거하고 stdout에 인쇄("팝업")하려면 해당 명령을tee:

tail -n 1 "$file" | tee >(wc -c | xargs -I {} truncate "$file" -s -{})

이러한 명령은 매우 큰 파일을 효율적으로 처리할 수 있습니다.이것은 Yossi의 대답과 비슷하고 영감을 얻었지만 몇 가지 추가 기능을 사용하는 것을 피합니다.

이러한 기능을 반복적으로 사용할 경우 오류 처리 및 기타 기능을 사용할 수 있습니다.poptail여기서 명령: https://github.com/donm/evenmoreutils

macOS에서는head -n -1작동하지 않지만 다음 명령을 사용할 수 있습니다.

cat file.txt | tail -r | tail -n +2 | tail -r
  1. tail -r입력에서 선의 순서를 반대로 합니다.

  2. tail -n +2입력에서 두 번째 줄부터 시작하는 모든 줄을 인쇄합니다.

Mac 사용자

파일 자체를 변경하지 않고 출력을 삭제하려면 다음을 수행합니다.

sed -e '$ d' foo.txt

입력 파일의 마지막 줄을 삭제하려면 다음을 수행합니다.

sed -i '' -e '$ d' foo.txt

echo -e '$d\nw\nq'| ed foo.txt

리눅스

$마지막 줄을 의미합니다.d삭제를 의미합니다.

sed '$d' ~/path/to/your/file/name

맥OS

의등물에 sed -i:

sed -i '' -e '$ d' ~/path/to/your/file/name
awk 'NR>1{print buf}{buf = $0}'

기본적으로 이 코드는 다음과 같습니다.

첫 번째 줄 뒤의 각 줄에 대해 버퍼링된 줄을 인쇄합니다.

각 라인에 대해 버퍼 재설정

버퍼가 한 줄씩 지연되어 1~n-1 줄을 인쇄하게 됩니다.

다음은 스폰지를 사용한 솔루션입니다( 많은 유틸리티 패키지에서 제공).

head -n -1 foo.txt | sponge foo.txt

솔루션 요약:

  1. 대용량 파일을 위한 빠른 솔루션을 원하는 경우 효율적인 tail or dd 접근 방식을 사용하십시오.

  2. 확장/축소가 쉽고 휴대하기 쉬운 것을 원하는 경우 리디렉션이동 접근 방식을 사용합니다.

  3. 경우 너무 축확장소하기/ 음에라다고지무이는일파우즉)moreutils패키지)는 문제가 되지 않으며, 당신은 사각팬츠의 팬입니다. 스폰지 접근법을 고려해 보십시오.

"리다이렉트 및 이동" 방식과 비교하여 스폰지 방식의 좋은 이점은 스폰지가 파일 권한을 유지한다는 것입니다.

스폰지는 "리다이렉트 앤 무브" 방식에 비해 훨씬 더 많은 RAM을 사용합니다.이것은 약간의 속도(약 20%)를 향상시키지만, 속도에 관심이 있다면 "효율적인 꼬리"와 dd 접근 방식이 방법입니다.

많은 양의 데이터를 처리하는 것이 정상이고 출력은 정상이지만 정크선이 하나 있습니다.

스크립트의 출력을 파이프로 연결한 경우:

sed - i '$ d' 다음 오류가 발생하고 마지막으로 출력이 전혀 없습니다. 입력 파일이 없습니다.

하지만 | 헤드-n-1은 효과가 있었습니다!

이 두 가지 솔루션 모두 다른 형태로 제공됩니다.저는 이것들이 조금 더 실용적이고 명확하며 유용하다는 것을 알았습니다.

dd 사용:

BADLINESCOUNT=1
ORIGINALFILE=/tmp/whatever
dd if=${ORIGINALFILE} of=${ORIGINALFILE}.tmp status=none bs=1 count=$(printf "$(stat --format=%s ${ORIGINALFILE}) - $(tail -n${BADLINESCOUNT} ${ORIGINALFILE} | wc -c)\n" | bc )
/bin/mv -f ${ORIGINALFILE}.tmp ${ORIGINALFILE}

잘라내기 사용:

BADLINESCOUNT=1
ORIGINALFILE=/tmp/whatever
truncate -s $(printf "$(stat --format=%s ${ORIGINALFILE}) - $(tail -n${BADLINESCOUNT} ${ORIGINALFILE} | wc -c)\n" | bc ) ${ORIGINALFILE}
awk "NR != `wc -l < text.file`" text.file &> newtext.file

이 토막글이 묘기를 부립니다.

zshrc 파일의 마지막 줄을 제거하려면 다음과 같이 하십시오.

cat ~/.zshrc
sed -i '' -e '$ d' ~/.zshrc
cat ~/.zshrc

마지막 n개의 줄을 제거하는 예제와 같은 방법도 사용할 수 있습니다.

a=0; 반면dose [$a -lt 4 ]; 력 -i '$d' 출력. a=txt; a =expr $a + 1 완료; 완료

파일(output.txt)에서 마지막 4줄을 제거하는 중입니다.

루비(1.9+)

ruby -ne 'BEGIN{prv=""};print prv ; prv=$_;' file

언급URL : https://stackoverflow.com/questions/4881930/remove-the-last-line-from-a-file-in-bash

반응형