Jak mohu manipulovat s daty založenými na poli z příkazového řádku? Například
- Jak mohu vytisknout pouze řádky, jejichž N-té pole je
foo? ? - Jak mohu vytisknout pouze řádky, jejichž N-té pole není
foo? - Jak mohu vytisknout pouze řádky, jejichž N-té pole odpovídá
foo? - Jak mohu změnit pole N na
foo?
Existuje standardní přístup nebo sada nástrojů, která usnadňuje manipulaci s daty založenými na poli na systémech *nix?
Přijatá odpověď:
Při práci s poli lze použít dva základní přístupy:i) použít nástroj, který polím rozumí; ii) použijte regulární výraz. První z nich je obvykle robustnější a jednodušší.
Mnoho z běžně dostupných nástrojů na *nix je buď výslovně navrženo tak, aby se vypořádalo s poli, nebo mají šikovné triky, které to usnadní.
1. Použijte nástroj, který rozumí polím
1.1 awk
Klasickým nástrojem je zde awk . Automaticky rozdělí každý vstupní řádek na pole (oddělovač polí je ve výchozím nastavení prázdný, ale lze jej změnit pomocí -F flag) a pole jsou pak dostupná pro awk skript jako $n kde n je číslo pole. První pole je $1 , druhý $2 atd.
-
Tisk řádků, jejichž 3. pole je
foo.awk '$3=="foo"' fileZměna oddělovače na
:awk -F":" '$3=="foo"' fileVýchozí akce
awkje tisknout. Výše uvedené příkazy tedy vytisknou všechny řádky, jejichž 3. pole jefoo. Při použití-F, můžete nastavit libovolné oddělovače polí a dokonce použít regulární výrazy. -
Jak mohu vytisknout pouze řádky, jejichž 3. pole není
foo?awk '$3!="foo"' file -
Jak mohu vytisknout pouze řádky, jejichž 3. pole odpovídá
foo?Pokud pouze hledáte pole, která odpovídají vzoru (například
fooodpovídáfoobar), použijte~místo==:awk '$3~/foo/' file -
Jak mohu vytisknout pouze řádky, jejichž 3. pole neodpovídá
foo?awk '$3!~/foo/' file -
Jak mohu změnit 3. pole na
foo?awk '$3="foo"' file
1.2 Perl
Další možností je perl jednovrstvé. Stejně jako awk je i Perl plnohodnotný skriptovací jazyk, ale lze jej spustit také jako program příkazového řádku, který jako vstup používá skript. Jeho chování je upraveno přepínači příkazového řádku, z nichž nejdůležitější pro tuto otázku jsou:
-e:skript, kterýperlby měl běžet;-n:čtení vstupního souboru řádek po řádku;-p:vytiskne každý vstupní řádek po použití skriptu daného-e;-l:odstranit koncové nové řádky z každého vstupního řádku a přidat nový řádek do každéhoprintzavolat;-a:awk-mode, rozdělit každý vstupní řádek do pole@F;-F:oddělovač pole pro-a.
Důležitý rozdíl oproti awk je to perl 's -a přepínač rozdělí soubory do pole. V Perlu začínají pole na 0, ne na 1. To znamená, že 2. pole je ve skutečnosti $F[1] a ne $F[2] . S ohledem na toto vše, perl ekvivalenty výše uvedených jsou:
-
Tisk řádků, jejichž 3. pole je
foo.perl -ane 'print if $F[2] eq "foo"' fileZměna oddělovače na
:perl -F":" -ane 'print if $F[2] eq "foo"' fileNa rozdíl od
awk,perlnelze použít regulární výrazy jako oddělovače polí. Musí to být konkrétní znak nebo řetězec. -
Jak mohu vytisknout pouze řádky, jejichž 3. pole není
foo?perl -ane 'print unless $F[2] eq "foo"' file -
Jak mohu vytisknout pouze řádky, jejichž 3. pole odpovídá
foo?perl -ane 'print if $F[2]=~/foo/' file -
Jak mohu vytisknout pouze řádky, jejichž 3. pole neodpovídá
foo?perl -lane 'print unless $F[2]=~/foo/' file -
Jak mohu změnit 3. pole na
foo?Tenhle je v Perlu trochu těžkopádnější. Obvyklý přístup je změnit hodnotu v
@Fpole a poté pole vytiskněte. S jednoduchými soubory oddělenými mezerou je to snadné:perl -lane '$F[2]="foo"; print "@F"' fileS jiným oddělovačem se budete muset
joinpole. V opačném případě bude vytištěno odděleně:perl -F: -lane '$F[2]="foo"; print join ":",@F' file
2. Používejte regulární výrazy
Myšlenka je zde použít regulární výraz (zkráceně „regex“), který definuje pozici cílového řetězce v řádku. Například v souboru, jehož pole jsou oddělena : , můžeme najít 2. pole tak, že porovnáme vše až do 1. : (1. pole) a poté hledejte druhé:
^[^:]*:[^:]*:
Tento regulární výraz znamená:
^:začátek řádku;[^]:negovaná třída znaků.[^:]znamená „cokoli kromě:“;*:0 nebo více z předchozího vzoru;::doslovný:;
Dohromady to znamená, že první [^:]* je první pole a druhé je druhé pole. Je zřejmé, že to není příliš praktické, pokud hledáte 14. pole, ale může být užitečné pro jednodušší věci. Jak to tedy implementujeme, abychom manipulovali s našimi daty? Existují různé nástroje, které to umí; v těchto příkladech budu používat sed ale velmi podobné věci můžete dělat s awk , perl nebo python .
-
Jak mohu vytisknout pouze řádky, jejichž 2. pole je
foo?sed -n '/^[^:]*:foo:/p' file-npotlačí normální výstup a/regex/pznamená „vytisknout všechny řádky, které odpovídaly regulárnímu výrazu. -
Jak mohu vytisknout pouze řádky, jejichž 2. pole není
foo?sed '/^[^:]*:foo:/d' fileLogická inverze k výše uvedenému. Zde je
/regex/dznamená „smazat všechny řádky, kterým odpovídá regulární výraz. -
Jak mohu vytisknout pouze řádky, jejichž 2. pole odpovídá
foo?sed -n '/^[^:]*:[^:]*foo/p' file -
Jak mohu vytisknout pouze řádky, jejichž 2. pole neodpovídá
foo?sed '/^[^:]*:[^:]*foo/d' file -
Jak mohu změnit 2. pole na
foo?sed 's/([^:]*:)[^:]*/1foo/' fileNebo, protože
sedsubstituce může přímo řešit výskyt vzorů jeho opakováním s jednoduchým číselným příznakem:sed 's/[^:]*/foo/2' file