다중 열 텍스트 파일을 처리하여 다른 다중 열 텍스트 파일을 얻는 방법은 무엇입니까?


17

텍스트 파일이 있습니다.

a   aa  aaa     b   bb  bbb     c   cc  ccc
d   dd  ddd     e   ee  eee     f   ff  fff
g   gg  ggg     h   hh  hhh     i   ii  iii
j   jj  jjj

어떻게 처리하고 다음과 같은 2 열 파일을 얻을 수 있습니까?

a   aa
aaa b
bb  bbb
c   cc
ccc d
dd  ddd
e   ee
eee f
ff  fff
g   gg
ggg h
hh  hhh
i   ii
iii j
jj  jjj

또는 다음과 같은 세 개의 열 파일 :

a   aa  aaa
b   bb  bbb
c   cc  ccc
d   dd  ddd
e   ee  eee
f   ff  fff
g   gg  ggg
h   hh  hhh
i   ii  iii
j   jj  jj

나는 awk 솔루션을 선호하지만 다른 솔루션도 환영합니다.

답변:


1

GNU awk를 한 번만 호출해도됩니다 :

reshape.awk

# Set awk to split input at whitespace characters and
# use tab as the output field separator 
BEGIN {
  RS="[ \t\n]+"
  OFS="\t"
}

# Print using OFS or ORS based on the element index
{
  printf "%s", $1 (NR%n == 0 ? ORS : OFS)
}

# Append a missing new-line when last row is not full
END { 
  if( NR%n != 0) 
    printf "\n"
}

다음과 같이 실행하십시오.

awk -f reshape.awk n=2 infile

또는 단일 라이너로 :

awk -v n=2 'BEGIN { RS="[ \t\n]+"; OFS="\t" } { printf "%s", $1 (NR%n == 0 ? ORS : OFS) } END { if( NR%n != 0) printf "\n" }' infile

산출:

a   aa
aaa b
bb  bbb
c   cc
ccc d
dd  ddd
e   ee
eee f
ff  fff
g   gg
ggg h
hh  hhh
i   ii
iii j
jj  jjj

또는과 n=3:

a   aa  aaa
b   bb  bbb
c   cc  ccc
d   dd  ddd
e   ee  eee
f   ff  fff
g   gg  ggg
h   hh  hhh
i   ii  iii
j   jj  jjj

이 사용하지 않는 $1과 같은 형식 으로 문자열은 printf?
와일드 카드

@Wildcard : 맞습니다 "%s", .... 사용하는 것이 더 안전합니다 . 업데이트
Thor

확인해 주셔서 감사합니다. :) 그런데이 awk질문에 대한 다른 대답 의 명령 에도 동일하게 적용됩니다 .
와일드 카드

20

각 필드를 한 줄에 놓고 열을 붙입니다.

한 줄의 각 필드

tr

tr -s ' ' '\n' < infile

grep

grep -o '[[:alnum:]]*' infile

sed

sed 's/\s\+/\n/g' infile

또는 더 휴대용 :

sed 's/\s\+/\
/g' infile

어 wk

awk '$1=$1' OFS='\n' infile

또는

awk -v OFS='\n' '$1=$1' infile

칼럼

2 열 :

... | paste - -

3 열 :

... | paste - - -

기타

sed

2 열 :

... | sed 'N; s/\n/\t/g'

3 열 :

... | sed 'N; N; s/\n/\t/g'

기타

xargs

... | xargs -n number-of-desired-columns

xargs가 사용하는 /bin/echo인쇄, 데이터를 조심 것과 옵션 같은 외모echo 이와 같이 해석됩니다.

어 wk

... | awk '{ printf "%s", $0 (NR%n==0?ORS:OFS) }' n=number-of-desired-columns OFS='\t'

홍보

... | pr -at -number-of-desired-columns

또는

... | pr -at -s$'\t' -number-of-desired-columns

autogen 패키지의 열

... | columns -c number-of-desired-columns

일반적인 출력 :

a   aa  aaa
b   bb  bbb
c   cc  ccc
d   dd  ddd
e   ee  eee
f   ff  fff
g   gg  ggg
h   hh  hhh
i   ii  iii
j   jj  jjj

2
슬램 덩크. +1 선생님
Steven Penny

xargs전화를 걸 echo거나 해서는 안 printf됩니까?
와일드 카드

1
@Wildcard : 기본적으로 xargs호출/bin/echo
Thor

1
와, 나도 몰랐어! 심지어 POSIX에 의해 지정됩니다 . 감사!
와일드 카드

@Wildcard : 문제 xargs/bin/echo일으키는 옵션처럼 보이는 데이터를 보내는 중 ... 경고를 추가했습니다.
Thor

9
$ sed -E 's/\s+/\n/g' ip.txt | paste - -
a   aa
aaa b
bb  bbb
c   cc
ccc d
dd  ddd
e   ee
eee f
ff  fff
g   gg
ggg h
hh  hhh
i   ii
iii j
jj  jjj

$ sed -E 's/\s+/\n/g' ip.txt | paste - - -
a   aa  aaa
b   bb  bbb
c   cc  ccc
d   dd  ddd
e   ee  eee
f   ff  fff
g   gg  ggg
h   hh  hhh
i   ii  iii
j   jj  jjj

9

와일드 카드가 지적했듯이, 이것은 파일이 잘 포맷 된 경우에만 작동합니다. 쉘에서 glob로 해석 할 특수 문자가없고 기본 단어 분할 규칙에 만족합니다. 파일이 해당 테스트를 "통과"하는지에 대한 질문이 있으면이 방법을 사용하지 마십시오.

한 가지 가능성은 printf그것을 사용 하는 것입니다.

printf '%s\t%s\n' $(cat your_file)

그러면 내용이 단어로 분할되고 그 내용을 your_file쌍으로 묶어 탭으로 인쇄합니다. %s에서 더 많은 형식 문자열을 사용하여 printf추가 열을 가질 수 있습니다.


1
특수 문자가 포함되지 않은 파일에 따라 다릅니다. 예를 들어 별표 (*)가 있으면 예상치 못한 결과가 발생합니다.
와일드 카드

4
perl -n0E 'say s/\s+/ ++$n % 4 ?"\t":"\n"/gre' file

(열 수로 4를 대체하십시오)


4

BSD rs(개편) 유틸리티 :

$ rs 0 2
a   aa  aaa     b   bb  bbb     c   cc  ccc
d   dd  ddd     e   ee  eee     f   ff  fff
g   gg  ggg     h   hh  hhh     i   ii  iii
j   jj  jjj
[Ctrl-D][Enter]
a    aa
aaa  b
bb   bbb
c    cc
ccc  d
dd   ddd
e    ee
eee  f
ff   fff
g    gg
ggg  h
hh   hhh
i    ii
iii  j
jj   jjj

0 2 . 지정 0은 "열에서 자동으로 행 계산"을 의미합니다.


3

파이썬 스크립트 접근.

여기서 기본 아이디어는 텍스트의 모든 단어를 하나의 목록으로 편평하게 만들고 두 번째 항목마다 줄 바꿈을 인쇄하는 것입니다 (두 열로 열). 당신은 3 열, 변경하려는 경우 index%2에을index%3

#!/usr/bin/env python3
import sys

items = [i for l in sys.stdin 
           for i in l.strip().split()]
line = []
for index,item in enumerate(items,1):
    line.append(item)
    if index%2 == 0:
       print("\t".join(line))
       line = []

샘플 출력 :

$ python recolumnate.py < input.txt                                            
a   aa
aaa b
bb  bbb
c   cc
ccc d
dd  ddd
e   ee
eee f
ff  fff
g   gg
ggg h
hh  hhh
i   ii
iii j
jj  jjj

3 열 버전 (위에서 언급 한 것처럼 index%3 == 0변경됨)

$ cat recolumnate.py                                                           
#!/usr/bin/env python3
import sys

items = [i for l in sys.stdin 
           for i in l.strip().split()]
line = []
for index,item in enumerate(items,1):
    line.append(item)
    if index%3 == 0:
       print("\t".join(line))
       line = []

$ python recolumnate.py < input.txt                                            
a   aa  aaa
b   bb  bbb
c   cc  ccc
d   dd  ddd
e   ee  eee
f   ff  fff
g   gg  ggg
h   hh  hhh
i   ii  iii
j   jj  jjj
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.