GNU/Linux >> Znalost Linux >  >> Linux

Odstranit duplicitní pole v daném sloupci?

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] a v v novějších verzích perl , 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
Související:Jak upravit soubor na místě?
Linux
  1. Jak najít a odstranit duplicitní fotografie v Linuxu

  2. Tisknout řádky, pokud daný sloupec začíná velkým písmenem?

  3. Odstranit přilehlé duplicitní řádky při zachování objednávky?

  1. 7 Příklady příkazů Linux Uniq k odstranění duplicitních řádků ze souboru

  2. Jak přesně duplikovat složku

  3. Odstraňte soubor bez dotazu

  1. Odstraňte klíč, jehož platnost vypršela, v APT

  2. Jak odstranit duplicitní řádky uvnitř textového souboru?

  3. Odebrat řádky na základě duplikátů v rámci jednoho sloupce bez řazení?