usando o awk para dividir uma linha em espaços simples não múltiplos

4

Estou tentando dividir uma linha que não tenho controle sobre o formato. Se os parâmetros 7 e 8 estiverem faltando, o que é possível, eles serão substituídos por um espaço para que eu acabe com

field1 field2 field3 field4 field5 field6   field9

No momento, neste campo de situação 9 está sendo lido como campo 7. Muita busca me levou a acreditar que o seguinte deveria funcionar, mas não está funcionando. É provavelmente algum pequeno erro de sintaxe da minha parte, mas não consigo identificá-lo.

word1='echo $LINE | awk 'BEGIN { FS="[ ]" } ; { print $9 }''
    
por dazedandconfused 01.11.2013 / 15:19

3 respostas

7

O parâmetro LINE não é citado, então wordsplitting acontece na expansão de $LINE em echo $LINE e pelo tempo em que awk recebe qualquer entrada, você tem 7 words (como visto pelo shell) todos separados por um único espaço. Você deseja que o echo imprima como um word (novamente, como visto pelo shell) para que o espaço em branco na sua linha não seja desconfigurado antes que o awk possa processá-lo. É isso que citando o parâmetro impede.

# How you want it to be given to awk:
$ printf '<%s> ' "$LINE"; echo
<field1 field2 field3 field4 field5 field6   field9> 
# Your attempt:
$ printf '<%s> ' $LINE; echo
<field1> <field2> <field3> <field4> <field5> <field6> <field9> 

Observe como o espaço em branco extra desapareceu entre o campo 6 e 9.

Você deve sempre citar expansões, é mais provável que você quebre algo não citando expansões do que citando-as.

    
por 01.11.2013 / 15:30
2

Um parâmetro muito útil no awk quando se lida com comprimento de entrada variável é o NF, o número de campos.

lastword='echo $LINE | awk '{ print $NF }''

Isso sempre imprime a última coluna, independentemente dos ausentes. Se alguns campos no meio estiverem faltando, a contagem regressiva do último campo funciona muito bem também.

Um arquivo de amostra no qual colunas ausentes / vazias são preenchidas com espaços, como em seu exemplo:

line1 field1 field2 field3 field4 field5 field6 field7 field8 field9
line2 field1 field2 field3 field4 field5 field6  field8 field9
line3 field1 field2 field3 field4 field5   field8 field9

e

awk '{print $1 " " $2 " " $(NF-1) " " $NF}' file

    line1 field1 field8 field9
    line2 field1 field8 field9
    line3 field1 field8 field9
    
por 01.11.2013 / 15:47
2

Para fazer isso em ksh93 :

set -f
IFS='  ' # two spaces
set -- $LINE
printf '%s\n' "$9"

A duplicação do espaço remove o comportamento especial pelo qual as sequências de espaços são consideradas como uma e os espaços iniciais e finais são ignorados, como em zsh .

    
por 01.11.2013 / 16:38