Chtěl bych z daného sloupce (v příkladu 2 $) odstranit duplicitní pole (oddělená čárkou).
Vstupní soubor:
A 1,2,3,4
B 4,5,6,3
C 2,15
Očekávaný výstup:
A 1,2,3,4
B 5,6
C 15
Přijatá odpověď:
perl -lpe 's/sKS+/join ",", grep {!$seen{$_}++} split ",", $&/e'
Výše uvedené můžete spustit takto:
$ perl -lpe 's/sKS+/join ",", grep {!$seen{$_}++} split ",", $&/e' afile
A 1,2,3,4
B 5,6
C 15
Jak to funguje
První volání perl
pomocí -lpe
dělá následující 3 věci.
-l[octal]
povolit zpracování konce řádku, specifikuje zakončení řádku-p
předpokládat smyčku jako -n, ale také tisknout řádek, jako sed-e program
jeden řádek programu (je povoleno několik -e, vynechat programový soubor)
Tím se soubor v podstatě přenese dovnitř, odstraní se nové řádky, zpracuje se řádek a poté se na něj připojí znak nového řádku, když je hotovo. Takže je to jen procházení souboru a spouštění našeho kódu v Perlu proti každému v pořadí.
Pokud jde o skutečný kód Perl:
s
znamená znak mezery (pět znaků[ fnrt]
av
v novějších verzíchperl
, například[[:space:]]
).K
Ponechte věci vlevo od K, nezahrnujte je do $&S+
jeden nebo více znaků není v sadě [ fnrtv]
join ",",
převezme výsledky a znovu připojí každé pole tak, aby bylo odděleno čárkou.
split ",", $&
vezme shody, které byly nalezeny pomocí S+
a rozdělte je pouze na pole bez čárky.
grep {!$seen{$_}++}
vezme číslo každého pole, přidá ho do hash, $seen{}
kde číslo každého pole je $_
když procházíme každým z nich. Pokaždé, když je číslo pole „viděno“, je započítáno pomocí ++
operátor, $seen{$_}++
.
grep{!$seen{$_}++}
vrátí hodnotu pole, pokud bylo vidět pouze jednou.
Upraveno, aby bylo vidět, co se děje
Pokud použijete tuto upravenou ohavnost, můžete vidět, co se děje, když se tato perlská jedna vložka pohybuje přes řádky ze souboru.
$ perl -lpe 's/sKS+/join ",", grep {!$seen{$_}++} split ",", $&/e; @a=keys %seen; @b=values %seen; print "keys: @a | vals: @b"' afile
keys: 4 1 3 2 | vals: 1 1 1 1
A 1,2,3,4
keys: 6 4 1 3 2 5 | vals: 1 2 1 2 1 1
B 5,6
keys: 6 4 1 3 2 15 5 | vals: 1 2 1 2 2 1 1
C 15
Toto vám ukazuje obsah $seen{}
na konci zpracování řádku ze souboru. Vezměme 2. řádek souboru.
B 4,5,6,3
A tady je to, co moje upravená verze ukazuje tento řádek jako:
keys: 6 4 1 3 2 15 5 | vals: 1 2 1 2 2 1 1
Takže to znamená, že jsme viděli pole # 6 (1krát), pole # 4 (2krát) atd. a pole # 5 (1krát). Takže když grep{...}
vrátí výsledky, vrátí výsledky z tohoto pole pouze v případě, že byl přítomen v tomto řádku (4,5,6,3) a pokud jsme jej viděli pouze jednou (6,1,15,5). Průnik těchto 2 seznamů je (5,6) a to je to, co vrátí grep
.
Odkazy
- perlre – perldoc.perl.org