awk FS com barras invertidas

0

Eu uso o comando find . -maxdepth 1 -not -type d que gera saída como ./filename.1.out

Eu canso a saída do comando find para awk . O objetivo é dividir o literal ./ ou . . Eu tenho que trabalhar usando:

find . -maxdepth 1 -not -type d | gawk 'BEGIN { FS = "(\./)|(\.)" } ; { print NF }'

Na verdade, funciona se eu derrubar a primeira barra invertida no primeiro conjunto de parênteses. Ex:

find . -maxdepth 1 -not -type d | gawk 'BEGIN { FS = "(\./)|(\.)" } ; { print NF }'

O que eu não entendo - e minha pergunta é por que isso não funciona se eu usar:

find . -maxdepth 1 -not -type d | gawk 'BEGIN { FS = "(\./)|(\.)" } ; { print NF }'

Por "não funcionar", quero dizer NF retorna com um número como se o segundo paren fosse um regex. personagem (para corresponder a qualquer tipo de personagem). Talvez eu esteja respondendo a minha própria pergunta ... mas quando olho para os comandos / comportamento, parece que a barra invertida inicial está sendo ignorada. Na verdade, houve uma mensagem de sequência de escape de aviso dizendo que \ . estava sendo tratado como simples '.' Mas eu realmente não entendi o que estava fazendo até começar a imprimir a NF.

E, de fato ... o awk doc para seqüências de escape ( link diga:

The backslash character itself is another character that cannot be included normally; you must write \ to put one backslash in the string or regexp.

Então, se eu quisesse usar um regex para corresponder a um cifrão, eu precisaria de FS="\$"

O post foi originalmente para perguntar por que estava acontecendo. Então eu acredito que eu possa ter juntado as coisas. Se eu estiver errado, por favor, me endireite.

    
por Gregg 22.02.2016 / 03:40

2 respostas

0

O valor FS foi verificado duas vezes, o primeiro como um valor de string e o segundo como um ERE (Consulte Convenções Lexical ).

E também, POSIX não especificou o comportamento de \c quando c não é um dos " , / , \ddd com d é um dos dígitos octal, \ , a , b , f , n , r , t , v . Então você não sabe se a string \c será passada como \c ou c para ERE.

gawk , nawk e A própria versão de Brian Kernighan você c , enquanto mawk lhe dá \c :

$ for AWK in gawk mawk nawk bk-awk; do
  printf '<%s>\n' "$AWK"
  echo | "$AWK" -F '\.' '{print FS}'
done
<gawk>
gawk: warning: escape sequence '\.' treated as plain '.'
.
<mawk>
\.
<nawk>
.
<bk-awk>
.

Como \ será sempre reconhecido como \ , você estará seguro com \c :

$ for AWK in gawk mawk nawk bk-awk; do
printf '<%s>\n' "$AWK"; echo | "$AWK" -F '\.' '{print FS}'
done
<gawk>
\.
<mawk>
\.
<nawk>
\.
<bk-awk>
\.

O valor da string de \c será \c , portanto, usá-lo como um ERE fornece o resultado desejado.

    
por 22.02.2016 / 11:33
0

\x torna-se um caractere em uma cadeia de aspas duplas (como na maioria das shells e C) antes de ser considerada como uma regex, portanto, você precisa digitar \. para construir \. .

Vamos testar isso (você não precisa dos parênteses porque o operador de alternância | tem a menor precedência):

$ echo ./a.b.c | gawk 'BEGIN { FS = "\.|\./" } { for (i=1; i<=NF; i++) { print i ": " $i } }'
gawk: cmd. line:1: warning: escape sequence '\.' treated as plain '.'
1: 
2: 
3: 
4: 
5: 
6: 
7: 

O aviso está dizendo que a seqüência de escape na string é supérflua. Então, o FS é .|./ e você está dividindo cada caractere, produzindo vários campos vazios.

Agora com o \ duplicado:

$ echo ./a.b.c | gawk 'BEGIN { FS = "\.|\./" } { for (i=1; i<=NF; i++) { print i ": " $i } }'
1: 
2: a
3: b
4: c
    
por 22.02.2016 / 05:55