Sınırsız sayıda sütun değiştirme


12

Sütunlu bir dosyam var. Örnek için aşağıya bakın:

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

1'in sonuncusu, ikincisinin sonuncusundan önce olduğu tüm sütunları değiştirmek istiyorum ... vb.

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

Bunu yapan bir astar ( awkveya sed) var mı?
Birinin awksadece birkaç sütun olduğunda kullanabileceğini biliyorum , ancak bunu binlerce sütunlu dosyalarda yapabilmek istiyorum.

tacbunu çizgiler için mükemmel yapar.
Sanırım sütunların eşdeğerini arıyorum.

rev sütundaki içeriği de değiştirdiği için benim için çalışmadı.


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

Yanıtlar:


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

Böyle basit bir iş için çok çalıştım. Her zaman daha basit daha iyidir. +1
Birei

10

Bunu küçük bir python betiği ile yapabilirsiniz:

#!/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

Python'u sakıncası yoksa, bu tek astar, her satırdaki boşlukla ayrılmış sütunların sırasını tersine çevirir:

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$ 

Yukarıdakiler de python2.7 ile çalışır:

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$ 

Bu yöntem test ettiğim tüm anserlerin en hızlısı.
Peter.O

4

Kullanmanın tek yolu awk.

İçeriği 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

Aşağıdaki awkkomutu çalıştırın :

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

Aşağıdaki sonuçla:

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

Bu yavaş, ancak bir geri alma özelliği var. Tek bir karakterden daha geniş olduklarında, alan ayırıcıların genişliğini korur. FWIW: Bu komut dosyasını iki kez çalıştırırsanız, sonuç orijinal ile aynı olur.

İşte senaryo.

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"

İşte bazı zaman karşılaştırmaları. Test dosyası 1 satır içeriyordu.

                      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

Sen edebilirsiniz kullanmak tacsadece önce ve sonra giriş aktarması gerekir. Bu, e-tablo hesap makinesi scve yardımcı aracıyla yapılabilir psc:

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

Olarak görülüyor burada .

Bu, tüm sütunlar dolduğunda en iyi sonucu verir.

dosyada

 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

ÇıkışDosyası

  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

Düzenle

PeterO tarafından belirtildiği gibi sc, 702 sütunluk bir sert sınır vardır, bu nedenle bu yöntem tarafından desteklenen maksimum boyuttur.


1
Sayıları kayan noktalara dönüştürür (benim için). 1-> 1.00. Ayrıca, 702'den fazla alan genişliğinde satırlar için hatalar alıyorum. 32768 sayısal sınırı ile ilgili gibi görünüyor ... ama oldukça hızlı, asis.
Peter.O

Ben kayan nokta dönüştürme görmüyorum, ama eklemeden -Siçin psckomuta dizeleri olarak her şeyi yorumlamak gerekir. 702 sütun sınırına gelince, bu zor bir sınır çünkü sadece A'dan ZZ'ye sütunlar destekleniyor (26 + 26 * 26), bunun hakkında bir yorum ekleyeceğim.
Thor

1
Aslında kayan nokta sorunu ok.I içine daha da aranır ve ben sadece ortaya .. yüzen noktaları kapıdan acele ediyorum gibi sonuçları kontrol gerektiğini keşfettik sonra o vurur 702 sınırını ... It 702 alanın 1 satırında python cevaplarından daha hızlıdır , ancak 100 satır için verilen tüm yöntemlerin en yavaşı olur :( ..
Python'dan

3

Bu boru hattı, önemli bir faktör tarafından diğer en hızlı cevaptan daha hızlıdır (sonuçlara bakın). O kullanır trve tac. Verilerinizde bulunmayan 2 ASCII bayt (\ x00- \ x7F) kullanmanız gerekir.

\x00tipik olarak iyi bir seçimdir, \x01ancak verilerde olmayan herhangi bir ASCII baytını kullanabilirsiniz.

Bu örnekte, ayırıcı karakterler olarak SPACE ve SEKME. Sınırlayıcılar çok baytlı veya tekli olabilir. Çıkış sınırlayıcı tek bir alandır.

İşte komut. Dosya adı numberof fields_x'i gösteriyornumber of lines

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

Kullanılmayan baytları kontrol etmek / kontrol etmek istiyorsanız, önceden bu isteğe bağlı awkkomut dosyası ile kontrol edebilirsiniz . Bu isteğe bağlı komut dosyasını çalıştırırken bile toplam süre, diğer yöntemlerden (şimdiye kadar :) hala önemli ölçüde daha hızlıdır. İşte ön işleme komut dosyası.

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

Bu awk betiği: 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}}}

İkinci komut dizisi, bu komut dosyası için char-ascii-not-in-streamzamanı içerir.

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

Ayrıca baskı olmadan da yapabilirsiniz f :

awk 'BEGIN{ORS=""} {for(k=NF;k>0;--k) {print $k; if (k==1) print "\n"; else print " "}} ' file
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.