텍스트 파일에서 n 번째 열 가져 오기


86

텍스트 파일이 있습니다.

1 Q0 1657 1 19.6117 Exp
1 Q0 1410 2 18.8302 Exp
2 Q0 3078 1 18.6695 Exp
2 Q0 2434 2 14.0508 Exp
2 Q0 3129 3 13.5495 Exp

나는 다음과 같이 모든 줄의 두 번째와 네 번째 단어를 취하고 싶습니다.

1657 19.6117
1410 18.8302
3078 18.6695
2434 14.0508
3129 13.5495

이 코드를 사용하고 있습니다.

 nol=$(cat "/path/of/my/text" | wc -l)
 x=1
 while  [ $x -le "$nol" ]
 do
     line=($(sed -n "$x"p /path/of/my/text)
     echo ""${line[1]}" "${line[3]}""  >> out.txt
     x=$(( $x + 1 ))
 done

작동하지만 매우 복잡하고 긴 텍스트 파일을 처리하는 데 오랜 시간이 걸립니다.

이 작업을 수행하는 더 간단한 방법이 있습니까?


1
두 번째 열이라는 모든 행의 두 번째 단어는 간단합니다!
Bernard

답변:


127

iirc :

cat filename.txt | awk '{ print $2 $4 }'

또는 의견에서 언급했듯이 :

awk '{ print $2 $4 }' filename.txt

16
UUOC !!! awk '{print $2,$4}' filename.txt(더 파이프, 하나 개의 프로그램이라고 함) 낫다
블루

5
@blue cat파일 이름을 지정하는 대신 bash 스크립트에서 자주 사용 합니다. 오버 헤드가 최소화되고 구문 cat ... | ... > ...이 입력이 무엇인지, 출력이 어디로 가는지 정말 멋지게 보여 주기 때문 입니다. 당신 말이 맞아요, 실제로 여기에서 필요하지 않습니다.
Tom van der Woerdt 2013-06-16

8
@TomvanderWoerdt : 가끔 < input awk '{ print $2 $4 }' > output그 목적을 위해 글 을 씁니다 .
ruakh

69

다음 cut명령을 사용할 수 있습니다 .

cut -d' ' -f3,5 < datafile.txt

인쇄물

1657 19.6117
1410 18.8302
3078 18.6695
2434 14.0508
3129 13.5495

그만큼

  • -d' '-의미, space구분자로 사용
  • -f3,5 -세 번째 및 다섯 번째 열 가져 오기

순수한 셸 솔루션으로 대용량 파일 의 cut경우 훨씬 빠릅니다 . 파일이 여러 공백으로 구분 된 경우 다음과 같이 먼저 제거 할 수 있습니다.

sed 's/[\t ][\t ]*/ /g' < datafile.txt | cut -d' ' -f3,5

여기서 (gnu) sed는 tab또는 space문자를 단일 space.

변형의 경우-여기에 펄 솔루션도 있습니다.

perl -lanE 'say "$F[2] $F[4]"' < datafile.txt

1
당신은 각 라인에 공간의 수를 보장하는 경우 ... 잘 작동 정확히 ... :)
rogerdpack

24

완전성을 위해 :

while read _ _ one _ two _; do
    echo "$one $two"
done < file.txt

_임의의 변수 대신 (예 :) junk도 사용할 수 있습니다. 요점은 열을 추출하는 것입니다.

데모:

$ while read _ _ one _ two _; do echo "$one $two"; done < /tmp/file.txt
1657 19.6117
1410 18.8302
3078 18.6695
2434 14.0508
3129 13.5495

멋지고 가독성이 좋으며 perls / awks / others가 필요하지 않습니다.
Petr Matousu

6

하나 더 간단한 변형-

$ while read line
  do
      set $line          # assigns words in line to positional parameters
      echo "$3 $5"
  done < file

4

파일에 n 줄이 포함되어 있으면 스크립트는 파일을 n 번 읽어야합니다 . 따라서 파일 길이를 두 배로 늘리면 스크립트가 수행하는 작업의 양이 네 배로 늘어납니다. 원하는 작업은 순서대로 줄을 반복하는 것이므로 거의 모든 작업이 버려집니다.

대신, 파일의 행을 반복하는 가장 좋은 방법 while은 condition-command가 read내장 된 루프 를 사용하는 것입니다 .

while IFS= read -r line ; do
    # $line is a single line of the file, as a single string
    : ... commands that use $line ...
done < input_file.txt

귀하의 경우, 라인을 배열로 나누고 싶고 read내장은 실제로 원하는 배열 변수를 채우기위한 특별한 지원을 가지고 있기 때문에 다음과 같이 작성할 수 있습니다.

while read -r -a line ; do
    echo ""${line[1]}" "${line[3]}"" >> out.txt
done < /path/of/my/text

또는 더 나은 방법 :

while read -r -a line ; do
    echo "${line[1]} ${line[3]}"
done < /path/of/my/text > out.txt

그러나 수행중인 작업에 대해서는 cut유틸리티를 사용할 수 있습니다 .

cut -d' ' -f2,4 < /path/of/my/text > out.txt

(또는 awkTom van der Woerdt가 제안한대로 또는 perl, 또는 sed).


선호 read이상 cut:이 필드 사이에 여러 공간에 대한 강력한 그리고 당신은 배열의 마법이 필요하지 않기 때문에while read word1 word2 word3 word4 rest; do doSomethingWith $word2 $word4; done
user829755

3

구조화 된 데이터를 사용하는 경우 실행 tr및 / 또는 다른 작업을 위해 추가 셸 프로세스를 호출하지 않는 추가 이점이 있습니다 cut. ...

(물론, 조건문과 건전한 대안을 사용하여 잘못된 입력을 방지하고 싶을 것입니다.)

...
while read line ; 
do 
    lineCols=( $line ) ;
    echo "${lineCols[0]}"
    echo "${lineCols[1]}"
done < $myFQFileToRead ; 
...
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.