Wie verarbeite ich eine mehrspaltige Textdatei, um eine weitere mehrspaltige Textdatei zu erhalten?


17

Ich habe eine Textdatei:

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

Wie kann ich es verarbeiten und eine 2-Spalten-Datei wie folgt erhalten:

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

Oder eine dreispaltige Datei wie diese:

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

Ich bevorzuge awk Lösung, aber andere Lösungen sind auch willkommen.

Antworten:


1

Sie können dies auch mit einem einzigen Aufruf von GNU awk tun:

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"
}

Führen Sie es so aus:

awk -f reshape.awk n=2 infile

Oder als Einzeiler:

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

Ausgabe:

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

Oder mit 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

Ist nicht diese Verwendung $1als Format - String zu printf?
Wildcard

@Wildcard: Richtig, es ist sicherer zu benutzen "%s", .... Aktualisiert
Thor

Danke für die Bestätigung. :) Gleiches gilt awkübrigens für den Befehl in deiner anderen Antwort auf diese Frage.
Wildcard

20

Setze jedes Feld in eine Zeile und post-columnate.

Jedes Feld in einer Zeile

tr

tr -s ' ' '\n' < infile

grep

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

sed

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

oder tragbarer:

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

awk

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

oder

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

Kolumne

Einfügen

Für 2 Spalten:

... | paste - -

Für 3 Spalten:

... | paste - - -

etc.

sed

Für 2 Spalten:

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

Für 3 Spalten:

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

etc.

xargs

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

Als xargsAnwendungen /bin/echopassen sie zu drucken, dass die Daten , die wie Optionen aussehen echoals solche interpretiert werden.

awk

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

pr

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

oder

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

Spalten (aus dem Autogen-Paket)

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

Typische Ausgabe:

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
Slam Dunk. +1 Sir
Steven Penny

Sollte die xargsLeitung nicht anrufen echooder printf?
Wildcard

1
@Wildcard: xargsAnrufe /bin/echostandardmäßig
Thor

1
Wow, ich hatte keine Ahnung! Es wird sogar von POSIX spezifiziert . Vielen Dank!
Wildcard

@Wildcard: Das Senden von Daten an scheint xargsOptionen zu sein, /bin/echodie Probleme verursachen ... Ich habe eine Warnung hinzugefügt.
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

Wie Wildcard hervorhob, funktioniert dies nur, wenn Ihre Datei gut formatiert ist. Es gibt keine Sonderzeichen, die die Shell als Globs interpretiert, und Sie sind mit den Standardregeln für die Wortteilung zufrieden. Wenn Sie Fragen dazu haben, ob Ihre Dateien diesen Test "bestehen", verwenden Sie diesen Ansatz nicht.

Eine Möglichkeit wäre, printfes so zu machen

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

Das führt eine Wortteilung auf den Inhalt von aus your_fileund verbindet sie und druckt sie mit Tabulatoren dazwischen. Sie können weitere %sFormatzeichenfolgen in verwenden printf, um zusätzliche Spalten zu erhalten.


1
Das hängt von der Datei ab, die keine Sonderzeichen enthält. Wenn es zum Beispiel Sternchen (*) enthält, erhalten Sie sehr unerwartete Ergebnisse.
Wildcard

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

(Ersetzen Sie 4 durch die Anzahl der Spalten)


4

BSD rs(Reshape) -Dienstprogramm:

$ 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 2ist Zeilen und Spalten . Die Angabe 0bedeutet "Zeilen automatisch aus Spalten berechnen".


3

Python-Skript-Ansatz.

Grundlegende Idee hierbei ist, alle Wörter in Ihrem Text in einer Liste zusammenzufassen und dann nach jedem zweiten Element eine neue Zeile auszudrucken (dh in zwei Spalten aufzuteilen). Wenn Sie 3 Spalten möchten, wechseln Sie index%2zuindex%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 = []

Beispielausgabe:

$ 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

Dreispaltige Version (wie oben erwähnt, nur index%3 == 0geändert)

$ 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
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.