탭으로 구분된 텍스트 파일을 가져와 각 줄을 80자로 자르는 명령은 무엇입니까?

탭으로 구분된 텍스트 파일을 가져와 각 줄을 80자로 자르는 명령은 무엇입니까?

(때때로) 탭으로 구분된 데이터가 포함된 여러 줄의 텍스트 파일이 있습니다. 나는 그것을 찾아볼 수 있도록 파일을 출력하고 싶습니다. 그래서 각 줄의 처음 80자만 보고 싶습니다. (나는 중요한 내용을 각 줄의 앞에 두도록 텍스트 파일을 디자인했습니다.)

나는 cat을 사용하여 파일의 각 줄을 읽고 각 줄을 파이프라인의 다음 명령으로 보낼 수 있다고 생각했습니다.

cat tabfile | cut -c -80

그런데 이게 깨진 것 같습니다. 나는 장난을 쳤고 grep이 작동하는 것 같았습니다. 하지만 그렇지 않다는 것을 알게 되었습니다(파일의 모든 줄에 80자 이상의 문자가 있는 것은 아닙니다). 탭이 잘리고 단일 문자로 계산되는 것 같습니다.

나는 시도했다:

cat tabfile | tr \t \040 | cut -c -80

공백 가독성을 제거하여 데이터가 약간 손상되지만. 그러나 그것은 작동하지 않았습니다. 도 아니다:

cat tabfile | tr \011 \040 | cut -c -80

어쩌면 내가 tr을 잘못 사용하고 있는 걸까요? 이전에 여러 공백을 제거하려고 tr에 문제가 있었던 적이 있습니다. (이 컴퓨터에서 액세스할 수 있는 tr 버전에는 여러 문자를 압축하기 위한 -s 옵션이 있는 것 같습니다. 더 사용해야 할 수도 있습니다.)

내가 장난을 쳤다면 Perl이나 awk, sed 등을 사용하여 이 작업을 수행할 수 있을 것이라고 확신합니다.

그러나 가능한 한 이식성이 있도록 (POSIX?) 일반 명령을 사용하는 솔루션을 원합니다. tr을 사용하게 되면 결국 탭을 문자로 변환하고, 계산을 수행하고, 계산을 잘라낸 다음 해당 문자를 다시 탭으로 변환하여 출력하려고 할 수 있습니다.

한 줄로 입력하거나 명령줄에 직접 입력할 필요는 없습니다. 스크립트를 사용하면 됩니다.


탭 파일에 대한 추가 정보:

언젠가는 데이터를 다른 프로그램으로 가져오고 싶을 수도 있기 때문에 탭을 사용하여 필드를 구분하고 있습니다. 따라서 콘텐츠 사이에 탭이 하나만 있는 경향이 있습니다. 하지만 일반 텍스트 파일을 볼 때 가독성을 높이기 위해 탭을 사용하여 콘텐츠를 세로 열에 정렬하기도 합니다. 즉, 특정 텍스트 부분의 경우 탭이 다음 필드를 위 및 아래 필드와 정렬하는 지점에 도달할 때까지 내용 끝을 공백으로 채웁니다.

DarkTurquoise #00CED1 바다, 하늘, 노 젓는 보트 자연
MediumSpringGreen #00FA9A 나무에 마법을 사용하세요  
라임 #00FF00 봄치킨과 과일 전용$

답변1

expand내 생각에 당신은 및/또는 를 찾고 있는 것 같습니다 unexpand. \tab 너비가 단일 문자가 아닌 8자로 계산되도록 하려는 것 같습니다 . fold동일한 작업을 수행하지만 입력을 자르는 대신 다음 줄로 줄 바꿈합니다. 내 생각엔 당신이 원하는 것:

expand < input | cut -c -80

expand그리고 unexpandPOSIX 지정:

  • expand유틸리티는 파일이나 표준 입력을 표준 출력에 기록하고 \tab 문자를 하나 이상의 문자로 바꿔야 합니다.공간다음 탭 정지까지 패딩하는 데 필요한 문자입니다. 어느백스페이스 키문자는 출력에 복사되어야 하며 탭 정지 계산의 열 위치 수가 감소하도록 해야 합니다.

매우 간단합니다. 그럼, 그것이 무엇을 하는지 봅시다:

unset c i; set --;                                                             
until [ "$((i+=1))" -gt 10 ]; do set -- "$@" "$i" "$i"; done                      
for c in 'tr \\t \ ' expand;  do eval '                                           
    { printf "%*s\t" "$@"; echo; } | 
      tee /dev/fd/2 |'"$c"'| { 
      tee /dev/fd/3 | wc -c >&2; } 3>&1 |
      tee /dev/fd/2 | cut -c -80'
done

상단의 루프는 다음 until과 같은 데이터 세트를 가져옵니다.

1 1 2 2 3 3 ...

printfarg 패딩 플래그를 사용 하므로 %*s세트의 각 인수에 대해 printf인수 수만큼 공백이 채워집니다. \t각각에 ab 문자를 추가합니다 .

모든 tee는 적용 시 각 필터의 ​​효과를 표시하는 데 사용됩니다.

효과는 다음과 같습니다.

1        2        3        4        5        6        7        8                9               10
1  2   3    4     5      6       7        8         9         10 
1  2   3    4     5      6       7        8         9         10 
66
1        2        3        4        5        6        7        8                9               10
1        2        3        4        5        6        7        8                9               10 
1        2        3        4        5        6        7        8                
105

행은 다음과 같이 두 그룹으로 배열됩니다.

  1. 산출printf ...; echo
  2. tr ...또는의 출력expand
  3. 산출cut
  4. 산출wc

처음 4개 행은 tr필터의 결과입니다. 여기서 각 \tab는 단일로 변환됩니다.공간.

그리고 마지막 4개의 체인 결과입니다 expand.

답변2

탭은 분리보다는 정렬에 더 적합하므로 한 가지 접근 방식은 column다음을 사용하는 것입니다 cut.

column -s '\t' -t <some-file | cut -c -80

POSIX가 아닌 것 같습니다 column. 이는 Ubuntu의 BSD 유틸리티의 일부이므로 상당히 크로스 플랫폼이라고 가정합니다.

답변3

댓글에 있는 Don의 제안은 좋은 시작입니다.

이것이 (주로) 작동하도록 만드는 데 필요한 것입니다.

pr +1 -1 -t -m -l1000 -w 80 tabfile

단일 열에 플래그를 적용 -m해야 합니다 . -w매뉴얼 페이지에서는 이를 나타내기 위해 일부 재작성을 사용할 수 있습니다.

해결 방법을 시도하는 동안 문자를 pr출력하여 입력하면 동일한 문제가 발생한다는 것을 발견했습니다 .\tcut

-1(열 플래그)는 매뉴얼 페이지에 지정되어 있습니다.

이 옵션은 -m과 함께 사용하면 안 됩니다.

그러나 이 옵션을 사용하지 않으면 pr줄이 지정된 길이보다 훨씬 짧게 임의로 잘립니다.

pr또한 필드의 모든 단어 앞(또는 뒤에?)에 공백을 삽입합니다(즉, 모든 곳에 공백이 있고 처리 후에 공백이 두 개 있습니다). 단어가 너무 많으면 삽입된 공백은 -w제한을 무시합니다(줄 바꿈 생성). 그러나 이상하게도 탭으로 구분되지 않은(예: 공백 정렬) "열"은 정렬된 상태로 유지됩니다.

답변4

디스플레이 너비를 실제로 이해해야 하는 유틸리티 중 하나는 다음과 같습니다 fold. 불행히도 랩 대신 폐기할 수 있는 옵션이 없는 것 같습니다. 매우 비효율적일 수도 있지만 다음과 같은 작업을 수행할 수 있습니다.

while read -r line; do fold -w80 <<< "$line" | head -n1; done < file

관련 정보