Drukowanie wszystkiego oprócz pierwszego pola za pomocą awk
Mam plik, który wygląda tak:
AE United Arab Emirates
AG Antigua & Barbuda
AN Netherlands Antilles
AS American Samoa
BA Bosnia and Herzegovina
BF Burkina Faso
BN Brunei Darussalam
A ja lubię odwracać kolejność, drukując najpierw wszystko oprócz $1 a potem $1:
United Arab Emirates AE
Jak mogę zrobić sztuczkę "wszystko poza polem 1"?
16 answers
Przypisanie $1
działa, ale pozostawia spację wiodącą: awk '{first = $1; $1 = ""; print $0, first; }'
Możesz również znaleźć liczbę kolumn w NF
i użyć jej w pętli.
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-11-16 19:32:13
$1=""
pozostawia spację, jak wspomniał Ben Jackson, więc użyj pętli for
:
awk '{for (i=2; i<=NF; i++) print $i}' filename
Więc jeśli twój łańcuch był "raz dwa trzy", wyjście będzie:
Dwa
trzy
Jeśli chcesz uzyskać wynik w jednym wierszu, możesz wykonać następujące czynności:
awk '{for (i=2; i<NF; i++) printf $i " "; print $NF}' filename
To da ci: "dwa trzy"
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-01-13 21:30:06
Użyj polecenia cut
z opcją --complement
:
$ echo a b c | cut -f 1 -d ' '
a
$ echo a b c | cut -f 1,2 -d ' '
a b
$ echo a b c | cut -f 1 -d ' ' --complement
b c
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-01-13 21:30:45
Może najbardziej zwięzły sposób:
$ awk '{$(NF+1)=$1;$1=""}sub(FS,"")' infile
United Arab Emirates AE
Antigua & Barbuda AG
Netherlands Antilles AN
American Samoa AS
Bosnia and Herzegovina BA
Burkina Faso BF
Brunei Darussalam BN
Wyjaśnienie:
$(NF+1)=$1
: Generator" nowego " ostatniego pola.
$1=""
: Ustaw oryginalne pierwsze pole na null
sub(FS,"")
: po pierwszych dwóch akcjach {$(NF+1)=$1;$1=""}
pozbądź się pierwszego separatora pól za pomocą sub. Ostateczny druk jest niejawny.
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-01-13 21:31:44
awk '{sub($1 FS,"")}7' YourFile
Usuń pierwsze pole i separator i wydrukuj wynik (7
jest wartością niezerową, więc Drukuj $0).
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-02-07 10:50:32
awk '{ saved = $1; $1 = ""; print substr($0, 2), saved }'
Ustawienie pierwszego pola na ""
pozostawia pojedynczą kopię OFS
na początku $0
. Zakładając, że OFS
jest tylko pojedynczym znakiem (domyślnie jest to pojedyncza spacja), możemy ją usunąć za pomocą substr($0, 2)
. Następnie dołączamy zapisaną kopię $1
.
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
2012-04-19 04:05:41
Jeśli jesteś otwarty na rozwiązanie Perla...
perl -lane 'print join " ",@F[1..$#F,0]' file
Jest prostym rozwiązaniem z separatorem wejścia/wyjścia jednej przestrzeni, który daje:
United Arab Emirates AE
Antigua & Barbuda AG
Netherlands Antilles AN
American Samoa AS
Bosnia and Herzegovina BA
Burkina Faso BF
Brunei Darussalam BN
Ten następny jest nieco bardziej złożony
perl -F` ` -lane 'print join " ",@F[1..$#F,0]' file
I zakłada, że separator wejścia/wyjścia ma dwie spacje:
United Arab Emirates AE
Antigua & Barbuda AG
Netherlands Antilles AN
American Samoa AS
Bosnia and Herzegovina BA
Burkina Faso BF
Brunei Darussalam BN
Używane są następujące opcje wiersza poleceń:
-
-n
pętla wokół każdej linii pliku wejściowego, nie Drukuj automatycznie każdej linii -
-l
usuwa nowe linie przed przetworzeniem, a następnie dodaje je z powrotem w -
-a
Tryb autosplit-podział linii wejściowych na tablicę @F. Domyślnie dzielenie na białe znaki -
-F
modyfikator autosplit, w tym przykładzie dzieli się na "" (dwie spacje) -
-e
wykonaj następujący kod Perla
@F
jest tablicą słów w każdej linii, indeksowaną zaczynając od 0$#F
jest liczbą słów w @F
@F[1..$#F]
jest tablicą kawałek elementu 1 przez ostatni element@F[1..$#F,0]
jest wycinkiem tablicy elementu 1 przez ostatni element plus element 0
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-09-17 15:57:25
Separator pól w gawk (przynajmniej) może być zarówno ciągiem znaków, jak i znakiem (może to być również regex). Jeśli Twoje dane są spójne, to zadziała:
awk -F " " '{print $2,$1}' inputfile
To dwie spacje między podwójnymi cudzysłowami.
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-11-16 20:34:53
awk '{ tmp = $1; sub(/^[^ ]+ +/, ""); print $0, tmp }'
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-11-16 22:02:05
Przenieśmy wszystkie rekordy do następnego i ustawmy ostatni jako pierwszy:
$ awk '{a=$1; for (i=2; i<=NF; i++) $(i-1)=$i; $NF=a}1' file
United Arab Emirates AE
Antigua & Barbuda AG
Netherlands Antilles AN
American Samoa AS
Bosnia and Herzegovina BA
Burkina Faso BF
Brunei Darussalam BN
Wyjaśnienie
-
a=$1
Zapisz pierwszą wartość do zmiennej tymczasowej. -
for (i=2; i<=NF; i++) $(i-1)=$i
Zapisz N-tą wartość pola do (N-1)tego pola. -
$NF=a
Zapisz pierwszą wartość ($1
) do ostatniego pola. -
{}1
true condition to makeawk
performing the default action:{print $0}
.
W ten sposób, jeśli zdarzy ci się mieć inny separator pola, wynik jest również dobry:
$ cat c
AE-United-Arab-Emirates
AG-Antigua-&-Barbuda
AN-Netherlands-Antilles
AS-American-Samoa
BA-Bosnia-and-Herzegovina
BF-Burkina-Faso
BN-Brunei-Darussalam
$ awk 'BEGIN{OFS=FS="-"}{a=$1; for (i=2; i<=NF; i++) $(i-1)=$i; $NF=a}1' c
United-Arab-Emirates-AE
Antigua-&-Barbuda-AG
Netherlands-Antilles-AN
American-Samoa-AS
Bosnia-and-Herzegovina-BA
Burkina-Faso-BF
Brunei-Darussalam-BN
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-11-14 09:46:23
Jeśli jesteś otwarty na inne rozwiązanie Perla:
perl -ple 's/^(\S+)\s+(.*)/$2 $1/' file
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-01-19 21:01:06
Pierwsze dźgnięcie wydaje się działać w twojej konkretnej sprawie.
awk '{ f = $1; i = $NF; while (i <= 0); gsub(/^[A-Z][A-Z][ ][ ]/,""); print $i, f; }'
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-11-16 20:42:09
Opcja 1
Istnieje rozwiązanie, które działa z niektórymi wersjami awk:
awk '{ $(NF+1)=$1;$1="";$0=$0;} NF=NF ' infile.txt
Wyjaśnienie:
$(NF+1)=$1 # add a new field equal to field 1.
$1="" # erase the contents of field 1.
$0=$0;} NF=NF # force a re-calc of fields.
# and use NF to promote a print.
Wynik:
United Arab Emirates AE
Antigua & Barbuda AG
Netherlands Antilles AN
American Samoa AS
Bosnia and Herzegovina BA
Burkina Faso BF
Brunei Darussalam BN
Może to jednak zawieść w starszych wersjach awk.
Opcja 2
awk '{ $(NF+1)=$1;$1="";sub(OFS,"");}1' infile.txt
Czyli:
awk '{ # call awk.
$(NF+1)=$1; # Add one trailing field.
$1=""; # Erase first field.
sub(OFS,""); # remove leading OFS.
}1' # print the line.
Zauważ, że to, co należy usunąć, to OFS, a nie FS. Linia jest ponownie obliczana, gdy pole $1 jest asigned. To zmienia wszystkie biegi FS do jednego z nich.
Ale nawet ta opcja nadal nie działa z kilkoma ogranicznikami, co jest wyraźnie pokazane przez zmianę OFS:
awk -v OFS=';' '{ $(NF+1)=$1;$1="";sub(OFS,"");}1' infile.txt
Ta linia wyświetli:
United;Arab;Emirates;AE
Antigua;&;Barbuda;AG
Netherlands;Antilles;AN
American;Samoa;AS
Bosnia;and;Herzegovina;BA
Burkina;Faso;BF
Brunei;Darussalam;BN
To pokazuje, że biegi FS są zmieniane na jeden z nich.
Jedynym sposobem, aby tego uniknąć, jest uniknięcie ponownego obliczenia pola.
Jedną z funkcji, która może uniknąć re-calc jest sub.
Pierwsze pole może zostać przechwycone, a następnie usunięte z $0 za pomocą sub, a następnie oba ponownie wydrukowane.
Opcja 3
awk '{ a=$1;sub("[^"FS"]+["FS"]+",""); print $0, a;}' infile.txt
a=$1 # capture first field.
sub( " # replace:
[^"FS"]+ # A run of non-FS
["FS"]+ # followed by a run of FS.
" , "" # for nothing.
) # Default to $0 (the whole line.
print $0, a # Print in reverse order, with OFS.
United Arab Emirates AE
Antigua & Barbuda AG
Netherlands Antilles AN
American Samoa AS
Bosnia and Herzegovina BA
Burkina Faso BF
Brunei Darussalam BN
Nawet jeśli zmienimy FS, OFS i / lub dodamy więcej ograniczniki, to działa.
Jeśli plik wejściowy zostanie zmieniony na:
AE..United....Arab....Emirates
AG..Antigua....&...Barbuda
AN..Netherlands...Antilles
AS..American...Samoa
BA..Bosnia...and...Herzegovina
BF..Burkina...Faso
BN..Brunei...Darussalam
I polecenie zmienia się na:
awk -vFS='.' -vOFS=';' '{a=$1;sub("[^"FS"]+["FS"]+",""); print $0,a;}' infile.txt
Wyjście będzie (nadal zachowując ograniczniki):
United....Arab....Emirates;AE
Antigua....&...Barbuda;AG
Netherlands...Antilles;AN
American...Samoa;AS
Bosnia...and...Herzegovina;BA
Burkina...Faso;BF
Brunei...Darussalam;BN
Polecenie może być rozszerzone do kilku pól, ale tylko z nowoczesnymi awk i z aktywną opcją --re-interval. To polecenie w oryginalnym pliku:
awk -vn=2 '{a=$1;b=$2;sub("([^"FS"]+["FS"]+){"n"}","");print $0,a,b;}' infile.txt
Wyświetli to:
Arab Emirates AE United
& Barbuda AG Antigua
Antilles AN Netherlands
Samoa AS American
and Herzegovina BA Bosnia
Faso BF Burkina
Darussalam BN Brunei
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
2020-06-20 09:12:55
Jest też opcja sed...
sed 's/\([^ ]*\) \(.*\)/\2 \1/' inputfile.txt
Wyjaśnione...
Swap
\([^ ]*\) = Match anything until we reach a space, store in $1
\(.*\) = Match everything else, store in $2
With
\2 = Retrieve $2
\1 = Retrieve $1
Dokładniej wyjaśnione...
s = Swap
/ = Beginning of source pattern
\( = start storing this value
[^ ] = text not matching the space character
* = 0 or more of the previous pattern
\) = stop storing this value
\( = start storing this value
. = any character
* = 0 or more of the previous pattern
\) = stop storing this value
/ = End of source pattern, beginning of replacement
\2 = Retrieve the 2nd stored value
\1 = Retrieve the 1st stored value
/ = end of replacement
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-05 10:14:42
Yet another way...
...to dołącza do pól 2 przez NF z FS i wyprowadza jedną linię na linię wejścia
awk '{for (i=2;i<=NF;i++){printf $i; if (i < NF) {printf FS};}printf RS}'
Używam tego z Gitem, aby zobaczyć, jakie pliki zostały zmodyfikowane w moim roboczym katalogu:
git diff| \
grep '\-\-git'| \
awk '{print$NF}'| \
awk -F"/" '{for (i=2;i<=NF;i++){printf $i; if (i < NF) {printf FS};}printf RS}'
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-05-12 00:52:52
Inny i łatwy sposób użycia polecenia cat
cat filename | awk '{print $2,$3,$4,$5,$6,$1}' > newfilename
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
2019-10-10 04:11:19