Używanie awk do wydrukowania drugiej kolumny i reszty tekstu z #

Mam takie linie w swoich plikach konfiguracyjnych,

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 

Chcę awk usunąć drugą kolumnę i elementy po #. Używam awk as

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

Nie jestem pewien, jak uzyskać tekst po #.
Preferowane wyjście to klucze, a następnie tekst komentarza jako

$mod+F2 Open terminal 

Odpowiedź

$ 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 

W tym celu awk najpierw wyodrębnia drugie pole w każdym wierszu zaczynając od bindsym do zmiennej key. Następnie usuwa wszystko, aż do # włącznie, w wierszu i drukuje key oraz to, co pozostało z wiersza z tabulatorem jako separator.

Alternatywne formatowanie wyjściowe:

$ 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 jest taka sama, ale na wyjściu przydziela się 20 znaków dla każdego z dwóch ( wyrównane do lewej) i umieszcza pomiędzy nimi tabulator (dla dokładności).

Odpowiedź

Używając match() funkcja GNU awk w celu dopasowania części od # do końca wiersza

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

Funkcja match() wypełnia tablicę podaną w trzecim argumencie dopasowanym wzorcem z wyrażenia regularnego w drugim argumencie .

w każdym POSIX awk trzeci argument match() nie jest obsługiwany , ale kilka specjalnych zmiennych RSTART i RLENGTH, które oznaczają początek i długość dopasowanej grupy. Używamy funkcji substr() w bieżącym wierszu, aby uzyskać dopasowany ciąg

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

Aby ładnie wydrukować wynik , możesz użyć funkcji printf() tak jak w drugiej odpowiedzi.

Odpowiedź

Jest to bardzo proste w sed; ponieważ Twoje dane nie są tak naprawdę zorientowane na pola, awk nie zapewnia tutaj ogromnych korzyści:

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

Tłumaczenie:

s/^[^ ]* // 

Usuń wszystko do pierwszego znaku spacji włącznie.

s/ .*#// 

Usuń wszystko od pierwszego (pozostałego) znaku spacji, aż do ostatniego # znaku w wierszu.

Odpowiedź

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 

Komentarze

  • I ' m zakładając, że mogą być więcej niż cztery wiersze plik wejściowy. Nie jest jasne, jaki byłby twój pierwszy krok poza wydrukowaniem numeru linii w terminalu.
  • Poprawianie kodu
  • Poprawienie kodu

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *