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.

Nur ein Anfänger
quelle

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
Thor
quelle
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
Thor
quelle
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
Sundeep
quelle
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.

Eric Renouf
quelle
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)

Joao
quelle
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".

Kaz
quelle
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
Sergiy Kolodyazhnyy
quelle