Skuteczny sposób na transpozycję pliku w Bash
Mam ogromny plik rozdzielony tabulatorami sformatowany tak
X column1 column2 column3
row1 0 1 2
row2 3 4 5
row3 6 7 8
row4 9 10 11
Chciałbym przetransponować w efektywny sposób używając tylko poleceń Basha (mógłbym napisać w tym celu skrypt Perla o około dziesięciu liniach, ale powinien być wolniejszy w wykonaniu niż natywne funkcje Basha). Więc wyjście powinno wyglądać tak:
X row1 row2 row3 row4
column1 0 3 6 9
column2 1 4 7 10
column3 2 5 8 11
Myślałem o takim rozwiązaniu
cols=`head -n 1 input | wc -w`
for (( i=1; i <= $cols; i++))
do cut -f $i input | tr $'\n' $'\t' | sed -e "s/\t$/\n/g" >> output
done
Ale to powolne i nie wydaje się najskuteczniejszym rozwiązaniem. Widziałem rozwiązanie dla vi w to post , ale i tak jest zbyt wolno. Jakieś pomysły/sugestie / genialne pomysły? :-) 25 answers
awk '
{
for (i=1; i<=NF; i++) {
a[NR,i] = $i
}
}
NF>p { p = NF }
END {
for(j=1; j<=p; j++) {
str=a[1,j]
for(i=2; i<=NR; i++){
str=str" "a[i,j];
}
print str
}
}' file
Wyjście
$ more file
0 1 2
3 4 5
6 7 8
9 10 11
$ ./shell.sh
0 3 6 9
1 4 7 10
2 5 8 11
Wydajność wobec rozwiązania Perla Jonathana na pliku 10000 linii
$ head -5 file
1 0 1 2
2 3 4 5
3 6 7 8
4 9 10 11
1 0 1 2
$ wc -l < file
10000
$ time perl test.pl file >/dev/null
real 0m0.480s
user 0m0.442s
sys 0m0.026s
$ time awk -f test.awk file >/dev/null
real 0m0.382s
user 0m0.367s
sys 0m0.011s
$ time perl test.pl file >/dev/null
real 0m0.481s
user 0m0.431s
sys 0m0.022s
$ time awk -f test.awk file >/dev/null
real 0m0.390s
user 0m0.370s
sys 0m0.010s
[[9]}EDIT by Ed Morton (@ghostdog74 zapraszam do usunięcia, jeśli nie zgadzasz się).
Być może ta wersja z bardziej wyraźnymi nazwami zmiennych pomoże odpowiedzieć na niektóre z poniższych pytań i ogólnie wyjaśni, co robi skrypt. Używa również tabulatorów jako separatora, o który pierwotnie prosił OP, aby obsłużyć puste pola i przypadkowo wyjście trochę dla tego konkretnego przypadku.
$ cat tst.awk
BEGIN { FS=OFS="\t" }
{
for (rowNr=1;rowNr<=NF;rowNr++) {
cell[rowNr,NR] = $rowNr
}
maxRows = (NF > maxRows ? NF : maxRows)
maxCols = NR
}
END {
for (rowNr=1;rowNr<=maxRows;rowNr++) {
for (colNr=1;colNr<=maxCols;colNr++) {
printf "%s%s", cell[rowNr,colNr], (colNr < maxCols ? OFS : ORS)
}
}
}
$ awk -f tst.awk file
X row1 row2 row3 row4
column1 0 3 6 9
column2 1 4 7 10
column3 2 5 8 11
Powyższe rozwiązania będą działać w każdym awk(oprócz starego, zepsutego awk oczywiście-tam YMMV).
Powyższe rozwiązania odczytują cały plik do pamięci - jeśli pliki wejściowe są na to zbyt duże, możesz to zrobić:
$ cat tst.awk
BEGIN { FS=OFS="\t" }
{ printf "%s%s", (FNR>1 ? OFS : ""), $ARGIND }
ENDFILE {
print ""
if (ARGIND < NF) {
ARGV[ARGC] = FILENAME
ARGC++
}
}
$ awk -f tst.awk file
X row1 row2 row3 row4
column1 0 3 6 9
column2 1 4 7 10
column3 2 5 8 11
Który prawie nie używa pamięci, ale odczytuje plik wejściowy raz na liczbę pól w linii, więc będzie znacznie wolniejszy niż wersja, która wczytuje cały plik do pamięci. Zakłada również liczba pól jest taka sama w każdej linii i używa GNU awk dla ENDFILE
i ARGIND
, ale każdy awk może zrobić to samo z testami na FNR==1
i END
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-10 15:39:03
Inną opcją jest użycie rs
:
rs -c' ' -C' ' -T
-c
zmienia separator kolumn Wejściowych, -C
zmienia separator kolumn wyjściowych, a -T
transponuje wiersze i kolumny. Nie używaj -t
zamiast -T
, ponieważ używa automatycznie obliczonej liczby wierszy i kolumn, która zwykle nie jest poprawna. rs
, którego nazwa pochodzi od funkcji przekształcania w APL, pochodzi z BSD i OS X, ale powinna być dostępna w menedżerach pakietów na innych platformach.
Sekunda opcja jest użycie Ruby:
ruby -e'puts readlines.map(&:split).transpose.map{|x|x*" "}'
Trzecią opcją jest użycie jq
:
jq -R .|jq -sr 'map(./" ")|transpose|map(join(" "))[]'
jq -R .
wypisuje każdą linię wejściową jako ciąg znaków JSON, -s
(--slurp
) tworzy tablicę dla linii wejściowych po przetworzeniu każdej linii jako JSON i -r
(--raw-output
) wypisuje zawartość ciągów zamiast liter ciągów JSON. Operator /
jest przeciążony do podzielonych łańcuchów.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-22 08:10:50
Rozwiązanie Pythona:
python -c "import sys; print('\n'.join(' '.join(c) for c in zip(*(l.split() for l in sys.stdin.readlines() if l.strip()))))" < input > output
Powyższe opiera się na następującej treści:
import sys
for c in zip(*(l.split() for l in sys.stdin.readlines() if l.strip())):
print(' '.join(c))
Ten kod zakłada, że każda linia ma taką samą liczbę kolumn(nie wykonuje się wypełnienia).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-11-13 17:21:00
Projekt transpose na sourceforge jest programem C podobnym do coreutil do tego właśnie celu.
gcc transpose.c -o transpose
./transpose -t input > output #works with stdin, too.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-08 17:36:25
Czysty BASH, bez dodatkowego procesu. Fajne ćwiczenie:
declare -a array=( ) # we build a 1-D-array
read -a line < "$1" # read the headline
COLS=${#line[@]} # save number of columns
index=0
while read -a line ; do
for (( COUNTER=0; COUNTER<${#line[@]}; COUNTER++ )); do
array[$index]=${line[$COUNTER]}
((index++))
done
done < "$1"
for (( ROW = 0; ROW < COLS; ROW++ )); do
for (( COUNTER = ROW; COUNTER < ${#array[@]}; COUNTER += COLS )); do
printf "%s\t" ${array[$COUNTER]}
done
printf "\n"
done
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-11-19 17:51:31
Oto umiarkowanie solidny skrypt Perla do wykonania zadania. Istnieje wiele analogii strukturalnych z rozwiązaniem @ghostdog74 awk
.
#!/bin/perl -w
#
# SO 1729824
use strict;
my(%data); # main storage
my($maxcol) = 0;
my($rownum) = 0;
while (<>)
{
my(@row) = split /\s+/;
my($colnum) = 0;
foreach my $val (@row)
{
$data{$rownum}{$colnum++} = $val;
}
$rownum++;
$maxcol = $colnum if $colnum > $maxcol;
}
my $maxrow = $rownum;
for (my $col = 0; $col < $maxcol; $col++)
{
for (my $row = 0; $row < $maxrow; $row++)
{
printf "%s%s", ($row == 0) ? "" : "\t",
defined $data{$row}{$col} ? $data{$row}{$col} : "";
}
print "\n";
}
Przy wielkości danych próbki różnica w wydajności między perlem a awk była znikoma (1 milisekunda z 7 ogółem). Z większym zestawem danych (matryca 100x100, wpisy po 6-8 znaków), perl nieznacznie przewyższa awk-0,026 s vs 0,042 s. żadne z nich nie może być problemem.
Reprezentacyjne timingi dla Perla 5.10.1 (32-bit) vs awk (wersja 20040207, gdy podano '-V') vs gawk 3.1.7 (32-bit) na MacOS X 10.5.8 na pliku zawierającym 10 000 linii z 5 kolumnami w linii:
Osiris JL: time gawk -f tr.awk xxx > /dev/null
real 0m0.367s
user 0m0.279s
sys 0m0.085s
Osiris JL: time perl -f transpose.pl xxx > /dev/null
real 0m0.138s
user 0m0.128s
sys 0m0.008s
Osiris JL: time awk -f tr.awk xxx > /dev/null
real 0m1.891s
user 0m0.924s
sys 0m0.961s
Osiris-2 JL:
Zauważ, że gawk jest znacznie szybszy niż awk na tej maszynie, ale nadal wolniejszy niż perl. Oczywiście twój przebieg będzie się różnić.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-11-16 15:35:28
Spójrz na GNU datamash , który może być używany tak jak datamash transpose
.
Przyszła wersja będzie również obsługiwać tabelę krzyżową (tabele przestawne)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-07 09:08:01
Jeśli masz sc
zainstalowane, można zrobić:
psc -r < inputfile | sc -W% - > outputfile
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-11-13 16:54:28
Zakładając, że wszystkie twoje wiersze mają taką samą liczbę pól, ten program awk rozwiązuje problem:
{for (f=1;f<=NF;f++) col[f] = col[f]":"$f} END {for (f=1;f<=NF;f++) print col[f]}
W słowach, gdy pętlujesz wiersze, dla każdego pola f
wyrastaj oddzielony od siebie łańcuch col[f]
zawierający elementy tego pola. Po zakończeniu wszystkich wierszy wydrukuj każdy z tych ciągów w osobnej linii. Następnie możesz zastąpić ':' separatorem, który chcesz (powiedzmy, spacją), przesyłając wyjście przez tr ':' ' '
.
Przykład:
$ echo "1 2 3\n4 5 6"
1 2 3
4 5 6
$ echo "1 2 3\n4 5 6" | awk '{for (f=1;f<=NF;f++) col[f] = col[f]":"$f} END {for (f=1;f<=NF;f++) print col[f]}' | tr ':' ' '
1 4
2 5
3 6
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-10 19:31:16
Jest do tego specjalnie skonstruowane narzędzie,
apt install datamash
datamash transpose < yourfile
Pobrane z tej strony, https://www.gnu.org/software/datamash/ i http://www.thelinuxrain.com/articles/transposing-rows-and-columns-3-methods
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-07 09:00:40
Jedyną poprawą, jaką widzę dla Twojego własnego przykładu, jest użycie awk, które zmniejszy liczbę uruchomionych procesów i ilość danych przesyłanych między nimi:
/bin/rm output 2> /dev/null
cols=`head -n 1 input | wc -w`
for (( i=1; i <= $cols; i++))
do
awk '{printf ("%s%s", tab, $'$i'); tab="\t"} END {print ""}' input
done >> output
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-11-13 16:08:51
Hakerskie rozwiązanie Perla może być takie. Jest to miłe, ponieważ nie ładuje wszystkich plików w pamięci, drukuje pośrednie pliki tymczasowe, a następnie używa all-wonderful paste
#!/usr/bin/perl
use warnings;
use strict;
my $counter;
open INPUT, "<$ARGV[0]" or die ("Unable to open input file!");
while (my $line = <INPUT>) {
chomp $line;
my @array = split ("\t",$line);
open OUTPUT, ">temp$." or die ("unable to open output file!");
print OUTPUT join ("\n",@array);
close OUTPUT;
$counter=$.;
}
close INPUT;
# paste files together
my $execute = "paste ";
foreach (1..$counter) {
$execute.="temp$counter ";
}
$execute.="> $ARGV[1]";
system $execute;
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-11-13 15:49:11
Użyłem rozwiązania fgm (dzięki fgm!), ale potrzebne do wyeliminowania znaków tabulacji na końcu każdego wiersza, więc zmodyfikował skrypt tak:
#!/bin/bash
declare -a array=( ) # we build a 1-D-array
read -a line < "$1" # read the headline
COLS=${#line[@]} # save number of columns
index=0
while read -a line; do
for (( COUNTER=0; COUNTER<${#line[@]}; COUNTER++ )); do
array[$index]=${line[$COUNTER]}
((index++))
done
done < "$1"
for (( ROW = 0; ROW < COLS; ROW++ )); do
for (( COUNTER = ROW; COUNTER < ${#array[@]}; COUNTER += COLS )); do
printf "%s" ${array[$COUNTER]}
if [ $COUNTER -lt $(( ${#array[@]} - $COLS )) ]
then
printf "\t"
fi
done
printf "\n"
done
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-03-21 22:39:57
Właśnie szukałem podobnego Basha, ale z obsługą paddingu. Oto scenariusz, który napisałem w oparciu o rozwiązanie fgm, który wydaje się działać. Jeśli to może pomóc...
#!/bin/bash
declare -a array=( ) # we build a 1-D-array
declare -a ncols=( ) # we build a 1-D-array containing number of elements of each row
SEPARATOR="\t";
PADDING="";
MAXROWS=0;
index=0
indexCol=0
while read -a line; do
ncols[$indexCol]=${#line[@]};
((indexCol++))
if [ ${#line[@]} -gt ${MAXROWS} ]
then
MAXROWS=${#line[@]}
fi
for (( COUNTER=0; COUNTER<${#line[@]}; COUNTER++ )); do
array[$index]=${line[$COUNTER]}
((index++))
done
done < "$1"
for (( ROW = 0; ROW < MAXROWS; ROW++ )); do
COUNTER=$ROW;
for (( indexCol=0; indexCol < ${#ncols[@]}; indexCol++ )); do
if [ $ROW -ge ${ncols[indexCol]} ]
then
printf $PADDING
else
printf "%s" ${array[$COUNTER]}
fi
if [ $((indexCol+1)) -lt ${#ncols[@]} ]
then
printf $SEPARATOR
fi
COUNTER=$(( COUNTER + ncols[indexCol] ))
done
printf "\n"
done
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-30 05:27:17
Szukałem rozwiązania do transponowania dowolnego rodzaju macierzy (nxn lub mxn) z dowolnymi danymi (liczbami lub danymi) i otrzymałem następujące rozwiązanie:
Row2Trans=number1
Col2Trans=number2
for ((i=1; $i <= Line2Trans; i++));do
for ((j=1; $j <=Col2Trans ; j++));do
awk -v var1="$i" -v var2="$j" 'BEGIN { FS = "," } ; NR==var1 {print $((var2)) }' $ARCHIVO >> Column_$i
done
done
paste -d',' `ls -mv Column_* | sed 's/,//g'` >> $ARCHIVO
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-06 04:41:33
Zwykle używam tego małego fragmentu awk
do tego wymagania:
awk '{for (i=1; i<=NF; i++) a[i,NR]=$i
max=(max<NF?NF:max)}
END {for (i=1; i<=max; i++)
{for (j=1; j<=NR; j++)
printf "%s%s", a[i,j], (j==NR?RS:FS)
}
}' file
To po prostu ładuje wszystkie dane do tablicy dwuwymiarowej a[line,column]
, a następnie drukuje je jako a[column,line]
, aby transponować dane wejściowe.
To musi śledzić max
imum ilość kolumn, które ma plik początkowy, tak, że jest używana jako liczba wierszy do wydrukowania z powrotem.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-12 07:48:30
Jeśli chcesz wyciągnąć z pliku tylko jedną (rozdzielaną przecinkami) linię $n i zamienić ją w kolumnę:
head -$N file | tail -1 | tr ',' '\n'
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-26 13:03:55
Niezbyt eleganckie, ale to polecenie" Jednowierszowe " szybko rozwiązuje problem:
cols=4; for((i=1;i<=$cols;i++)); do \
awk '{print $'$i'}' input | tr '\n' ' '; echo; \
done
Tutaj cols jest liczbą kolumn, gdzie można zastąpić 4 przez head -n 1 input | wc -w
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-01 03:47:20
#!/bin/bash
aline="$(head -n 1 file.txt)"
set -- $aline
colNum=$#
#set -x
while read line; do
set -- $line
for i in $(seq $colNum); do
eval col$i="\"\$col$i \$$i\""
done
done < file.txt
for i in $(seq $colNum); do
eval echo \${col$i}
done
Kolejna wersja z set
eval
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-19 07:43:32
Inne rozwiązanie awk
i ograniczone dane wejściowe o wielkości posiadanej pamięci.
awk '{ for (i=1; i<=NF; i++) RtoC[i]= (RtoC[i]? RtoC[i] FS $i: $i) }
END{ for (i in RtoC) print RtoC[i] }' infile
To łączy wszystkie te same pozycje liczb zespolonych i in END
wypisuje wynik, który byłby pierwszym wierszem w pierwszej kolumnie, drugim wierszem w drugiej kolumnie, itd.
Wyjście:
X row1 row2 row3 row4
column1 0 3 6 9
column2 1 4 7 10
column3 2 5 8 11
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-19 16:51:14
Oto rozwiązanie Haskella. Po skompilowaniu z-O2, działa nieco szybciej niż awk ghostdoga i nieco wolniej niż cienko owinięty C python Stephana na mojej maszynie dla powtarzających się linii wejściowych "Hello world". Niestety wsparcie GHC dla przekazywania kodu linii poleceń nie istnieje, o ile mogę powiedzieć, więc będziesz musiał napisać go do pliku samodzielnie. Spowoduje to obcięcie wierszy do długości najkrótszego wiersza.
transpose :: [[a]] -> [[a]]
transpose = foldr (zipWith (:)) (repeat [])
main :: IO ()
main = interact $ unlines . map unwords . transpose . map words . lines
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-26 03:03:40
Rozwiązanie awk, które przechowuje całą tablicę w pamięci
awk '$0!~/^$/{ i++;
split($0,arr,FS);
for (j in arr) {
out[i,j]=arr[j];
if (maxr<j){ maxr=j} # max number of output rows.
}
}
END {
maxc=i # max number of output columns.
for (j=1; j<=maxr; j++) {
for (i=1; i<=maxc; i++) {
printf( "%s:", out[i,j])
}
printf( "%s\n","" )
}
}' infile
Ale możemy" chodzić " po Pliku tyle razy, ile potrzeba wierszy wyjściowych:
#!/bin/bash
maxf="$(awk '{if (mf<NF); mf=NF}; END{print mf}' infile)"
rowcount=maxf
for (( i=1; i<=rowcount; i++ )); do
awk -v i="$i" -F " " '{printf("%s\t ", $i)}' infile
echo
done
Który (dla małej liczby wierszy wyjściowych jest szybszy niż poprzedni kod).
Niektóre * Nix standard util jednolinijkowe, nie potrzebne pliki tymczasowe. Uwaga: OP chciał efektywny naprawić, (tzn. szybciej), a najlepsze odpowiedzi są zwykle szybsze. Te one-linery są dla tych, którzy lubią *nix "narzędzia programowe", z jakichkolwiek powodów. W rzadkich przypadkach (np. skąpe IO i pamięć) fragmenty te mogą być szybsze.
Wywołanie pliku wejściowego foo.
-
Jeśli wiemy foo ma cztery kolumny:
for f in 1 2 3 4 ; do cut -d ' ' -f $f foo | xargs echo ; done
-
Jeśli nie wiemy ile kolumn foo mA:
n=$(head -n 1 foo | wc -w) for f in $(seq 1 $n) ; do cut -d ' ' -f $f foo | xargs echo ; done
xargs
ma limit rozmiaru i dlatego zrobi niekompletną pracę z długim plikiem. Jaki limit wielkości jest zależny od systemu, np.:{ timeout '.01' xargs --show-limits ; } 2>&1 | grep Max
Maksymalna długość polecenia, którego możemy użyć: 2088944
-
tr
&echo
:for f in 1 2 3 4 ; do cut -d ' ' -f $f foo | tr '\n\ ' ' ; echo ; done
...lub jeśli # kolumn jest nieznany:
n=$(head -n 1 foo | wc -w) for f in $(seq 1 $n); do cut -d ' ' -f $f foo | tr '\n\ ' ' ; echo ; done
-
Za pomocą
set
, które jakxargs
, ma podobne ograniczenia w zależności od rozmiaru wiersza poleceń:for f in 1 2 3 4 ; do set - $(cut -d ' ' -f $f foo) ; echo $@ ; done
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-21 15:33:26
Oto Bash one-liner, który opiera się na prostej konwersji każdej linii do kolumny ipaste
-ing them together:
echo '' > tmp1; \
cat m.txt | while read l ; \
do paste tmp1 <(echo $l | tr -s ' ' \\n) > tmp2; \
cp tmp2 tmp1; \
done; \
cat tmp1
M.txt:
0 1 2
4 5 6
7 8 9
10 11 12
Tworzy plik
tmp1
, aby nie był pusty.Odczytuje każdą linię i przekształca ją w kolumnę za pomocą
tr
-
Wkleja nową kolumnę do pliku
tmp1
Kopiuje wynik z powrotem do
tmp1
.
PS: naprawdę chciałem użyć io-deskryptorów, ale nie mogłem ich zmusić do praca.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-19 07:35:47
GNU datamash ( https://www.gnu.org/software/datamash ) doskonale nadaje się do tego problemu z tylko jedną linią kodu i potencjalnie arbitralnie dużym rozmiarem pliku! datamash-W transponuje input_file.txt > input_file_transposed.txt
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-07 15:00:34