Tenho esse tipo de linha em meus arquivos de configuração,
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
Eu quero awk
a segunda coluna e coisas que estão depois de #
. Estou usando awk
como
awk "/bindsym/{print $2}" filename
Não tenho certeza de como obter o texto após #
.
A saída preferida é as chaves e o texto do comentário como
$mod+F2 Open terminal
Resposta
$ 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
Isso usa awk
para primeiro extrair o segundo campo em cada linha começando com bindsym
na variável key
. Em seguida, ele exclui tudo até e incluindo #
na linha e imprime key
e o que resta da linha com uma guia como delimitador.
Formatação de saída alternativa:
$ 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
A lógica é a mesma, mas a saída aloca 20 caracteres para cada um dos dois ( justificado à esquerda) e coloca uma tabulação entre eles (para uma boa medida).
Resposta
Usando o match()
função do GNU awk
para corresponder à parte de #
até o final da linha
awk "/bindsym/ && match($0,/#(.+)$/,arr){print $2, arr[1]}" filep
A função match()
preenche a matriz fornecida no terceiro argumento com o padrão correspondente do regex no segundo argumento .
em qualquer POSIX awk
, o terceiro argumento de match()
não é compatível , mas algumas variáveis especiais RSTART
e RLENGTH
que marcam o início e o comprimento do grupo correspondido. Usamos a função substr()
na linha atual para obter a string correspondente
awk "/bindsym/ && match($0,/#(.+)$/){print $2, substr($0,RSTART+1,RLENGTH)}" file
Para imprimir a saída , você pode usar a função printf()
como na outra resposta.
Resposta
Isso é muito simples de fazer em sed
; já que seus dados não são realmente orientados para o campo, o Awk não fornece um grande benefício aqui:
sed "s/^[^ ]* //;s/ .*#//" inputfile
Tradução:
s/^[^ ]* //
Exclua tudo até e incluindo o primeiro caractere de espaço.
s/ .*#//
Exclua tudo do primeiro (restante) caractere de espaço, até o último #
caractere na linha.
Resposta
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
Comentários
- Eu ' estou supondo que pode haver mais de quatro linhas em o arquivo de entrada. Não está claro o que sua primeira etapa faria além de imprimir o número da linha no terminal.
- Correção do código
- Corrigido o código