텍스트 파일의 각 줄에있는 문자 수를 인쇄하는 방법


82

유닉스 명령을 사용하여 텍스트 파일의 각 줄에있는 문자 수를 인쇄하고 싶습니다. powershell로 간단하다는 것을 알고 있습니다.

gc abc.txt | % {$_.length}

하지만 유닉스 명령이 필요합니다.

답변:


152

Awk를 사용하십시오.

awk '{ print length }' abc.txt

2
이것은 각 줄에 wc -c를 적용하는 것보다 몇 배 더 빠릅니다!
aerijman

이러한 유형의 문제에 대해 @aerijman은 일반적으로 프로세스 생성 횟수가 성능 차이를 가장 많이 만드는 요소입니다.
MarcH

파일의 줄에 이모티콘이 포함되어 있으면 예상 길이가 생성되지 않습니다.
user5507535

@ user5507535, 실제로 예상하는 "길이"에 따라 다릅니다. 유니 코드에 대한 가능한 정의가 많이 있습니다 (mawk는 바이트를 사용하고 gawk를 확인하지 않음).
Jan Hudec 2019

16
while IFS= read -r line; do echo ${#line}; done < abc.txt

POSIX이므로 모든 곳에서 작동합니다.

편집 : William이 제안한대로 -r을 추가했습니다.

편집 : 유니 코드 처리에주의하십시오. 로케일이 올바르게 설정된 Bash 및 zsh는 코드 포인트 수를 표시하지만 dash는 바이트를 표시하므로 쉘이 수행하는 작업을 확인해야합니다. 그리고 어쨌든 유니 코드에는 길이에 대한 다른 많은 정의가 있으므로 실제로 원하는 것에 따라 다릅니다.

편집 : IFS=앞뒤 공백을 잃지 않도록 접두어를 붙입니다 .


+1하지만 ... 입력에 '\'가 포함되어 있으면 실패합니다. 사용 -r 읽기
윌리엄 Pursell

파일의 줄에 이모티콘이 포함되어 있으면 예상 길이가 생성되지 않습니다.
user5507535

@ user5507535, 실제로 예상하는 "길이"에 따라 다릅니다. 유니 코드에 대한 가능한 정의가 많이 있습니다 (그러나이 경우 다른 쉘은 실제로 다른 작업을 수행합니다).
Jan Hudec 2019

임의의 데이터를 읽고 자 할 때 항상 명령 IFS=에 설정 하십시오 read. 그래서 IFS= read -r. to do word splitting을 read사용하고 IFS, 모든 분할 단어가 사용 가능한 하나의 변수 ( line)에 다시 붙여 넣어 지더라도 원래의 모든 구분 문자와 함께 다시 붙여 넣어 지거나 잠재적으로 다른 하나만 붙여진다는 보장은 없습니다. 하나. 예를 들어, 기본 IFS를 사용하면 줄 foo barfoo bar으로 바뀌어 7 개의 공백이 손실 될 수 있습니다. (이 주석의 예제 문자열에서 Stack Overflow가 인접한 공백을 잃어버린 것과 같습니다).
mtraceur

@mtraceur, 문서에는 "나머지 단어와 그 사이에있는 구분 기호가성에 할당됩니다"라고 명시 적으로 나와 있으므로 원래 구분 기호와 함께 다시 붙여 넣습니다. 그러나 실제로 손실되는 선행후행 구분 기호 는 처리하지 않습니다 . 그래서 당신이 옳고, IFS설정되어야하지만, 그렇지 않을 때의 문제는 더 미묘합니다.
Jan Hudec

4

위에 나열된 다른 답변을 시도했지만 대용량 파일을 다룰 때 특히 한 줄의 크기가 사용 가능한 RAM의 1/4 이상을 차지하면 적절한 솔루션과는 거리가 멀습니다.

bash와 awk 모두이 문제에 대해서는 필요하지 않지만 전체 라인을 슬러 핑합니다. 줄이 너무 길면 메모리가 충분하더라도 Bash는 오류가 발생합니다.

저는 매우 간단하고 최적화되지 않은 파이썬 스크립트를 구현했습니다.이 스크립트는 대용량 파일 (한 줄에 최대 4GB)로 테스트 할 때 소리가 나지 않으며 주어진 것보다 훨씬 더 나은 솔루션입니다.

이것이 프로덕션에 시간이 중요한 코드 인 경우 C로 아이디어를 다시 작성하거나 읽기 호출에서 더 나은 최적화를 수행 할 수 있습니다 (한 번에 한 바이트 만 읽는 대신), 이것이 실제로 병목 현상인지 테스트 한 후.

코드는 줄 바꿈 문자가 Unix에서는 좋은 가정이지만 Mac OS / Windows에서는 YMMV라고 가정합니다. 마지막 줄 문자 수를 간과하지 않도록 파일이 줄 바꿈으로 끝나는 지 확인하십시오.

from sys import stdin, exit

counter = 0
while True:
    byte = stdin.buffer.read(1)
    counter += 1
    if not byte:
        exit()
    if byte == b'\x0a':
        print(counter-1)
        counter = 0

1
질문은 "텍스트"파일에 대한 것이 었습니다. 한 줄에 4GB가 텍스트 파일의 합리적인 정의에 맞지 않는다고 생각합니다.
MarcH 2011

3

다음은 사용하는 예입니다 xargs.

$ xargs -d '\n' -I% sh -c 'echo % | wc -c' < file

이 "echo %"는 쉘에서 인용해야하는 안전하지 않은 문자를 처리하지 않습니다. 또한 "xargs"는 원본 포스터가 요청한대로 줄 바꿈뿐만 아니라 공백과 줄 바꿈으로 파일을 분할합니다.
bovine

1

이 시도:

while read line    
do    
    echo -e |wc -m      
done <abc.txt    

당신은 의미 echo -e | wc -m하지 않습니까? 쓸모없는 명령 사용입니다. 쉘은 변수의 문자를 계산할 수 있습니다. Plus echo -e는 완전히 호환되지 않으며 일부 이스케이프 시퀀스로 시작하여 다른 일부에서는 작동하고 나머지에서는 아무것도 작동하지 않는 동안 쉘의 절반에서 작동합니다.
Jan Hudec
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.