파일을 줄 단위로 자르는 방법?


13

파일 수가 많으며 그 중 일부는 매우 깁니다. 파일 끝을 제거하여 더 큰 경우 특정 크기로 자르고 싶습니다. 그러나 나는 전체 줄만 제거하고 싶습니다. 어떻게해야합니까? Linux 툴체인이 처리하는 것과 같은 느낌이지만 올바른 명령을 모르겠습니다.

예를 들어 300 바이트 줄이있는 120,000 바이트 파일이 있고 10,000 바이트로 자르려고한다고 가정합니다. 처음 33 줄은 유지되어야하고 (9900 바이트) 나머지는 잘 려야합니다. 10,000 줄을 정확하게 자르고 싶지 않습니다. 왜냐하면 부분 줄을 남기기 때문입니다.

물론 파일의 길이가 다르고 선의 길이가 모두 같은 것은 아닙니다.

이상적으로 결과 파일은 약간 길지 않고 약간 짧게 만들어 지지만 (브레이크 포인트가 긴 줄에있는 경우) 그다지 중요하지 않은 경우 더 쉬울 수 있습니다. 파일을 직접 변경하고 싶습니다 (새 파일은 다른 곳으로 복사, 원본이 삭제되고 새 파일이 이동했지만 사용자의 POV와 동일합니다). 데이터를 여러 장소로 리디렉션 한 다음 다시 파일을 손상시킬 가능성을 초대하는 솔루션은 피하고 싶습니다 ...


내 대답을 삭제했습니다 ... 바이트의 파일 크기가 너무 명확하지 않은 것 같습니다. 죄송합니다. 질문을 편집하고 해당 부분을 명확하게 설명 할 수 있습니까 (예를 들어)?
slhck

@ slhck : 내가 명확하지 않아서 담당자를 잃어버린 것을 유감스럽게 생각합니다 ... 그 문제를 해결할 수 있는지 알려 드리겠습니다.
Charles

걱정 마세요, 방금 물어
봤어야 했어요

답변:


1

sed/의 wc경우 복잡성은 이전의 답변에 방지 할 수 있습니다 awk사용됩니다. OP에서 제공된 예제 사용 ( 10000 바이트 이전에 완전한 행 표시 ) :

awk '{i += (length() + 1); if (i <= 10000) print $ALL}' myfile.txt

또한 해당 바이트가 라인의 끝에 있지 않은 경우 10000 번째 바이트를 포함하는 완전한 라인을 표시합니다.

awk '{i += (length() + 1); print $ALL; if (i >= 10000) exit}' myfile.txt

위의 답변은 다음과 같이 가정합니다.

  1. 텍스트 파일은 Unix 줄 종결 자 ( \n)입니다. 도스 / 윈도우 텍스트 파일 (위해 \r\n), 변화 length() + 1length() + 2
  2. 텍스트 파일에는 단일 바이트 문자 만 포함됩니다. 멀티 바이트 문자가있는 경우 (예 : 유니 코드 환경에서) LC_CTYPE=C바이트 수준에서 해석을 강제 실행하도록 환경 을 설정하십시오 .

15

sed접근 방식은 괜찮지 만 모든 라인을 통해 루프 없습니다. 몇 줄을 유지하고 싶은지 알고 있다면 (예를 들어 99를 사용합니다) 다음과 같이 할 수 있습니다.

sed -i '100,$ d' myfile.txt

설명 : sed정규식 프로세서입니다. -i지정된 옵션을 사용하면 파일을 읽고 결과를 표준 출력에 쓰는 대신 파일을 직접 처리합니다 ( "인라인"). 100,$"100 행부터 파일의 끝까지"를 의미하고 명령 뒤에 d"삭제"를 나타내는 것으로 추측됩니다. 즉, 명령은 "myfile.txt에서 100 행부터 파일 끝까지의 모든 행을 삭제합니다"를 의미합니다. 99 행을 유지하려면 100이 첫 번째로 삭제됩니다.

편집 : 반면에 마지막 100 줄 을 유지하려는 로그 파일이있는 경우 :

[ $(wc -l myfile.txt) -gt 100 ] && sed -i "1,$(($(wc -l myfile.txt|awk '{print $1}') - 100)) d" myfile.txt

여기서 무슨 일이 일어나고 있습니까?

  • [ $(wc -l myfile.txt) -gt 100 ]: 파일에 100 줄 이상이있는 경우에만 다음을 수행하십시오.
  • $((100 - $(wc -l myfile.txt|awk '{print $1}'))): 삭제할 줄 수 계산 (예 : (마지막) 100을 제외한 파일의 모든 줄)
  • 1, $((..)) d: 첫 번째 줄부터 계산 된 줄까지 모든 줄을 제거합니다.

편집 : 자세한 내용을 제공하기 위해 질문을 방금 편집 했으므로이 추가 정보를 답변과 함께 포함시킵니다. 추가 된 사실은 다음과 같습니다.

  • 특정 크기 는 파일과 함께 남아 있어야합니다 (10,000 바이트)
  • 각 줄은 바이트 단위의 특정 크기를가집니다 (이 예에서는 300 바이트)

이 데이터에서 "/"로 유지 될 줄 수를 계산할 수 있습니다. 예를 들어 33 줄을 의미합니다. 계산을위한 쉘 용어 : $((size_to_remain / linesize))(적어도 Bash를 사용하는 Linux에서는 결과는 정수임) 조정 된 명령은 이제 다음과 같습니다.

# keep the start of the file (OPs question)
sed -i '34,$ d' myfile.txt
# keep the end of the file (my second example)
[ $(wc -l myfile.txt) -gt 33 ] && sed -i "1,33 d" myfile.txt

크기가 미리 알려져 있으므로 더 이상 sed명령에 포함 된 계산이 필요하지 않습니다 . 그러나 유연성을 위해 일부 쉘 스크립트 내에서 변수를 사용할 수 있습니다.

파일 크기에 따른 조건부 처리의 경우 다음 "test"-construct를 사용할 수 있습니다.

[ "$(ls -lk $file | awk ' {print $5}')" -gt 100 ] &&

"크기 $file가 100kB 를 초과하면 수행 ..."을 의미합니다 ( ls -lk위치 5에서 파일 크기를 kB로 나열하므로 awk정확하게 추출하는 데 사용됨).


OP는 행의 길이뿐만 아니라 특정 바이트 크기를 기준으로 파일을 자르려고합니다. 에 관련된 답변을 삭제했습니다 head -n.
slhck

@slhck 감사합니다. 예, OP는 의도를보다 명확하게하기 위해 질문을 편집했습니다. 그는 각 줄의 바이트 수를 계산할 수있는 수단을 가지고 있기 때문에 내 대답은 원칙적으로 유효합니다. 남은 줄 수를 계산 한 다음 내 접근 방식을 사용하여 파일을 처리 할 수 ​​있습니다. 어쩌면 나는 대답 내에서 그것에 대해 간단히 언급 할 것입니다.
Izzy

아니요-크기를 미리 알 수 없습니다. 그게 예입니다. 각 파일의 크기가 다르고 줄 길이가 불규칙합니다. 일부 파일은 전혀 잘리지 않아도됩니다.
Charles

아, 다시 ... 글쎄, 어떤 것들을 명확하게 설명하기가 어렵습니다 자르지 않아도되는 파일은 아마도 파일 크기를 기반으로합니까? 그것은 덮을 수 있습니다. 그러나 평균 라인 크기조차 알려지지 않은 경우,이 부분은 어려워집니다. 현재 오버 헤드없이 너무 쉬운 솔루션은 생각할 수 없습니다.
Izzy

현재 내가 생각해 낼 수있는 것은 예를 들어 첫 번째 n 줄을 가져 와서 그에 따라 평균 길이를 계산 하고이 값을 사용하는 것입니다. 도움이 되겠습니까?
Izzy

0

이 작업을 수행하는 명령을 찾지 못하면 빠른 스크립트 (테스트되지 않음)를 작성했습니다.

#!/bin/sh

# Usage: $0 glob.* 25000
# where glob.* is a wildcard pattern and 25000 is the maximum number of bytes.

limit=20000
tmp=/tmp/trim
[[ "$2" == +([0-9]) ]] || limit=$2
limit=`expr $len + 1`
for file in $1;
do
    [[ `wc -c $file` -lt $limit ]] && continue
    head -c $file > $tmp
    sed '$d' $tmp
    $tmp > $file
done

-1

linux 명령 sed를 사용하여 파일에서 행을 제거 할 수 있습니다. 다음 명령은 filename.txt의 마지막 줄을 삭제합니다.

sed '$d' filename.txt

awk 또는 find를 사용하면 sed 명령과 일치하는 패턴을 검색 할 수 있습니다. 먼저 awk로 검색하거나 단축하려는 파일을 찾은 다음 sed로 줄을 제거 할 수 있습니다.


-1

꼬리와 비슷한 것을했습니다. 이 경우 마지막 10,000 행만 유지하려면 다음을 수행하십시오.

TMP=$(tail -n 10000 /path/to/some/file 2>/dev/null) && echo "${TMP}" > /path/to/some/file
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.