Pomocí awk k tisku 2. sloupce a zbytku textu z #

Mám tyto typy řádků ve svých konfiguračních souborech,

bindsym $mod+F2 exec gnome-terminal #Open terminal bindsym $mod+p exec command /some/path" #Popup Dictionary bindsym $mod+Mod1+l exec --no-startup-id /some/path/command #Dmenu for my books collection bindsym Mod1+Control+b exec rxvt -e nnn #nnn file browser 

Chci awk vyjmout druhý sloupec a věci, které jsou za #. Používám awk as

awk "/bindsym/{print $2}" filename 

Nejsem si však jistý, jak získat text po #.
Upřednostňovaným výstupem jsou klíče a poté text komentáře jako

$mod+F2 Open terminal 

odpověď

$ awk -v OFS="\t" "/^bindsym/ { key = $2; sub(".*#", ""); print key, $0 }" file $mod+F2 Open terminal $mod+p Popup Dictionary $mod+Mod1+l Dmenu for my books collection Mod1+Control+b nnn file browser 

Pomocí awk se nejprve extrahuje druhé pole na každém řádku začínající bindsym do proměnné key. Poté odstraní vše až po # na řádku a vytiskne key a co zbývá z řádku se záložkou jako oddělovač.

Alternativní formátování výstupu:

$ awk "/^bindsym/ { key = $2; sub(".*#", ""); printf("%-20s\t%-20s\n", key, $0) }" file $mod+F2 Open terminal $mod+p Popup Dictionary $mod+Mod1+l Dmenu for my books collection Mod1+Control+b nnn file browser 

Logika je stejná, ale výstupu je pro každý z nich přiděleno 20 znaků ( pole zarovnaná vlevo) a umístí mezi ně záložku (pro správnou míru).

Odpovědět

Použití match() funkce GNU awk tak, aby odpovídala části od # do konce řádku

awk "/bindsym/ && match($0,/#(.+)$/,arr){print $2, arr[1]}" filep 

Funkce match() naplní pole poskytnuté ve třetím argumentu odpovídajícím vzorem z regexu ve druhém argumentu .

na libovolném POSIX awk není třetí argument match() nepodporován , ale několik speciálních proměnných RSTART a RLENGTH, které označují začátek a délku shodné skupiny. K získání shodného řetězce používáme funkci substr() na aktuálním řádku

awk "/bindsym/ && match($0,/#(.+)$/){print $2, substr($0,RSTART+1,RLENGTH)}" file 

Chcete-li výstup pěkně vytisknout , můžete buď použít funkci printf() jako v jiné odpovědi.

Odpověď

Toto je velmi jednoduché v sed; protože vaše data opravdu nejsou orientovaná na pole Awk zde neposkytují obrovskou výhodu:

sed "s/^[^ ]* //;s/ .*#//" inputfile 

Překlad:

s/^[^ ]* // 

Smazat vše až po první znak mezery včetně.

s/ .*#// 

Smazat vše od prvního (zbývajícího) znaku mezery, až po poslední # znak na řádku.

Odpověď

Step1: count=`awk "{print NR}"|sed -n "$p" filename` Step2:for ((i=1;i<=$count;i++)); do awk -v i="$i" "NR==i && $0 ~ /^bindsym/{print $2}" filename; sed -n ""$i"s/.*#//p" filename; done| sed "N;s/\n/ /g" output for ((i=1;i<=$count;i++)); do awk -v i="$i" "NR==i && $0 ~ /^bindsym/{print $2}" filename; sed -n ""$i"s/.*#//p" filename; done| sed "N;s/\n/ /g" $mod+F2 Open terminal $mod+p Popup Dictionary $mod+Mod1+l Dmenu for my books collection Mod1+Control+b nnn file browser 

Komentáře

  • I ' m za předpokladu, že v řádku mohou být více než čtyři řádky vstupní soubor. Není jasné, co by udělal váš první krok, než vytisknout číslo řádku v terminálu.
  • Oprava kódu
  • Oprava kódu

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *