무제한의 열 교환


12

열이있는 파일이 있습니다. 예를 들어 아래를 참조하십시오.

a b c ... z  
1 2 3 ... 26

첫 번째가 마지막이되고 두 번째가 마지막 이전이되는 모든 열을 바꾸고 싶습니다.

z y x ... a  
26 25 24 ... 1

이것을 수행하는 하나의 라이너 ( awk또는 sed)가 있습니까? 열이 몇 개인 경우
사용할 수 awk있지만 수천 개의 열이있는 파일 에서이 작업을 수행하고 싶습니다.

tac라인에 완벽하게 적용됩니다.
나는 열과 동등한 것을 찾고 있다고 생각합니다.

rev 열의 내용을 교환하기 때문에 나에게는 효과가 없었습니다.


perl -lane 'print join " ", reverse @F'

답변:


15
awk '{for(i=NF;i>0;i--)printf "%s ",$i;print ""}' file

나는 그런 간단한 일을하기 위해 너무 열심히 일했습니다. 항상 더 간단합니다. +1
Birei

10

작은 파이썬 스크립트로 할 수 있습니다 :

#!/usr/bin/env python

# Swaps order of columns in file, writes result to a file.
# usage: program.py input_file output_file

import sys, os

out = []

for line in open(sys.argv[1], 'r'):
    fields = line.split()
    rev = ' '.join(list(reversed(fields)))
    out.append(rev)

f = open(sys.argv[2], 'w')
f.write(os.linesep.join(out))

7

파이썬을 신경 쓰지 않으면이 하나의 라이너는 모든 줄에서 공백으로 구분 된 열의 순서를 반대로합니다.

paddy$ cat infile.txt 
a b c d e f g h i j k l
1 2 3 4 5 6 7 8 9 10 11 12
a e i o u
paddy$ python3 -c 'with open("infile.txt") as f: print("\n".join(" ".join(line.rstrip().split()[::-1]) for line in f))'
l k j i h g f e d c b a
12 11 10 9 8 7 6 5 4 3 2 1
u o i e a
paddy$ 

위의 내용은 python2.7에서도 작동합니다.

paddy$ python2.7 -c 'with open("infile.txt") as f: print("\n".join(" ".join(line.rstrip().split()[::-1]) for line in f))'
l k j i h g f e d c b a
12 11 10 9 8 7 6 5 4 3 2 1
u o i e a
paddy$ 

이 방법은 내가 테스트 한 모든 답변 중 가장 빠릅니다.
Peter.O

4

를 사용하는 한 가지 방법 awk.

내용 infile:

a b c d e f g h i j k l
1 2 3 4 5 6 7 8 9 10 11 12
a e i o u

다음 awk명령을 실행하십시오 .

awk '{
    ## Variable 'i' will be incremented from first field, variable 'j'
    ## will be decremented from last field. And their values will be exchanged.
    ## The loop will end when both values cross themselves.
    j = NF; 
    for ( i = 1; i <= NF; i++ ) { 
        if ( j - i < 1 ) { 
            break;
        } 
        temp = $j; 
        $j = $i; 
        $i = temp; 
        j--; 
    }
    print;
}' infile

결과는 다음과 같습니다.

l k j i h g f e d c b a
12 11 10 9 8 7 6 5 4 3 2 1
u o i e a

3

속도는 느리지 만 하나의 교환 기능이 있습니다. 단일 문자보다 넓은 필드 구분 기호의 너비를 유지합니다. FWIW :이 스크립트를 두 번 실행하면 결과가 원본과 동일합니다.

여기 스크립트가 있습니다.

awk '{ eix = length($0) 
       for( fn=NF; fn>0; fn--) { dix=eix
            while( substr($0,dix,1) ~ /[ \t]/ ) dix--
            printf "%s%s", substr($0,dix+1,eix-dix), $fn
            dix-=length($fn); eix=dix }
       print substr($0,1,dix)
    }' "$file"

시간 비교는 다음과 같습니다. 테스트 파일에는 한 줄이 포함되어 있습니다.

                      fields           fields     
                      10,0000          10,000,000

user11136 {python} | real  0.029s     real  3.235s
reversible? no     | user  0.032s     user  2.008s
                   | sys   0.000s     sys   1.228s

jmp {python}       | real  0.078s     real  5.045s
reversible? no     | user  0.068s     user  4.268s
                   | sys   0.012s     sys   0.560s

rush {awk}         | real  0.120s     real  10.889s
reversible? no     | user  0.116s     user   8.641s
                   | sys   0.008s     sys    2.252s

petero {awk}       | real  0.319s     real  35.750s
reversible? yes    | user  0.304s     user  33.090s
                   | sys   0.016s     sys    2.660s

3

당신은 할 수 사용 tac방금 전과 후에 입력을 전치 할 필요가있다. 이것은 스프레드 시트 계산기 sc와 그 조수 로 수행 할 수 있습니다 psc.

< infile psc -S -r | sc -W% - | tac | psc -S -r | sc -W% - > outfile

여기에서 볼 수 있듯이 .

이것은 모든 열이 채워질 때 가장 잘 작동합니다.

파일

 a b c d e f g h i  j  k  l
 1 2 3 4 5 6 7 8 9 10 11 12
 A B C D E F G H I  J  K  L

아웃 파일

  l  k  j i h g f e d c b a
 12 11 10 9 8 7 6 5 4 3 2 1
  L  K  J I H G F E D C B A

편집하다

PeterO sc 가 지적한 것처럼 702 열의 하드 제한이 있으므로이 방법이 지원하는 최대 크기입니다.


1
예를 들어 숫자를 부동 소수점으로 변환합니다. 1-> 1.00. 또한 702 개 이상의 필드 너비에 대한 오류가 발생합니다. 32768 의 숫자 제한과 관련이있는 것 같습니다 ...하지만 매우 빠릅니다.
Peter.O

부동 소수점 변환은 보이지 않지만 명령에 추가 -S하면 psc모든 것이 문자열로 해석되어야합니다. 702 열 제한과 관련하여 A ~ ZZ 열만 지원되므로 (26 + 26 * 26) 하드 제한입니다. 이에 대한 의견을 추가하겠습니다.
Thor

1
실제로 부동 소수점 문제는 괜찮습니다. 더 자세히 살펴 보았고 문을 서두르면서 결과를 확인해서는 안된다는 것을 발견했습니다. 부동 소수점 은 702 한계에 도달 한 후에 만 발생 합니다 ... 빠른에 대한 파이썬 답변보다 1 개 702 개 필드 라인 만 100 개 선을 위해 모든 주어진 방법 중 가장 느린된다 :( .. 그것은 파이썬보다 짧은 시동 시간이 있어야합니다.
Peter.O

3

이 파이프 라인은 다른 요인 중 가장 빠른 답변보다 빠릅니다 (결과 참조). 그것은 사용 tr하고 tac. 데이터에 존재하지 않는 2 개의 ASCII 바이트 (\ x00- \ x7F)를 사용해야합니다.

\x00는 일반적으로 좋은 선택 \x01이지만 데이터에없는 ASCII 바이트를 사용할 수 있습니다.

이 예에서 SPACE 및 TAB은 분리 문자입니다. 분리 문자는 멀티 바이트 또는 단일 일 수 있습니다. 출력 분리 문자는 단일 공백입니다.

명령은 다음과 같습니다. 파일 이름은 numberof fields_x를 보여줍니다number of lines

 <"$file" tr ' \t\n' '\0\0\1' |tr -s '\0' '\n' |tac |tr '\n' ' ' |tr '\1' '\n'

사용하지 않는 바이트를 확인 / 필요한 경우이 선택적 awk스크립트를 사용 하여 미리 확인할 수 있습니다 . 이 선택적 스크립트를 실행할 때도 전체 시간은 여전히 ​​다른 방법보다 훨씬 빠릅니다 (지금까지 :). 다음은 사전 처리 스크립트입니다.

o=($(<"$file" char-ascii-not-in-stream)); x="${o[0]}"; y="${o[1]}"
<"$file" tr ' \t\n' "$x$x$y" |tr -s "$x" '\n' |tac |tr '\n' ' ' | tr '$y' '\n' >"$file".$user

이것은 awk 스크립트입니다. char-ascii-not-in-stream

#!/usr/bin/awk -f
{c[$0]} END{for(i=0;i<=127;i++) {if(sprintf("%c", i) in c);else {printf "\\%03o ",i}}}

이 스크립트의 두 번째 시간 집합에는 시간이 포함 char-ascii-not-in-stream됩니다.

Peter.O {tr,tac,tr} ==== file_10_x10000
real    0m0.013s    0m0.015s
user    0m0.020s    0m0.020s
sys     0m0.008s    0m0.012s   

user11136 {python} ===== file_10_x10000
real    0m0.057s
user    0m0.048s
sys     0m0.008s

jmp {python} =========== file_10_x10000
real    0m0.160s
user    0m0.160s
sys     0m0.000s

rush {awk} ============= file_10_x10000
real    0m0.121s
user    0m0.120s
sys     0m0.000s

##############################################

Peter.O {tr,tac,tr} ==== file_1000_x1000
real    0m0.048s    0m0.059s
user    0m0.040s    0m0.040s
sys     0m0.040s    0m0.048s

user11136 {python} ===== file_1000_x1000
real    0m0.158s
user    0m0.136s
sys     0m0.028s

jmp {python} =========== file_1000_x1000
real    0m0.327s
user    0m0.320s
sys     0m0.008s

rush {awk} ============= file_1000_x1000
real    0m0.832s
user    0m0.820s
sys     0m0s012s

##############################################

Peter.O {tr,tac,tr} ==== file_1000000_x50
real    0m5.221s    0m6.458s
user    0m4.208s    0m5.248s
sys     0m2.624s    0m2.396s

user11136 {python} ===== file_1000000_x50
real    0m16.286s
user    0m10.041s
sys     0m5.148s

jmp {python} =========== file_1000000_x50
real    0m22.845s
user    0m20.705s
sys     0m1.140s

rush {awk} ============= file_1000000_x50
real    0m44.793s
user    0m43.583s
sys     0m0.848s

##############################################

0

당신은 또한 인쇄 하지 않고 그것을 할 수 있습니다 f :

awk 'BEGIN{ORS=""} {for(k=NF;k>0;--k) {print $k; if (k==1) print "\n"; else print " "}} ' file
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.