Valores separados por tabulação em awk


89

Como seleciono a primeira coluna da string separada por TAB?

# echo "LOAD_SETTLED    LOAD_INIT       2011-01-13 03:50:01" | awk -F'\t' '{print $1}'

O exemplo acima retornará a linha inteira e não apenas "LOAD_SETTLED" como esperado.

Atualizar:

Preciso alterar a terceira coluna nos valores separados por tabulação. O seguinte não funciona.

echo $line | awk 'BEGIN { -v var="$mycol_new" FS = "[ \t]+" } ; { print $1 $2 var $4 $5 $6 $7 $8 $9 }' >> /pdump/temp.txt

No entanto, isso funciona conforme o esperado se o separador for vírgula em vez de tabulação.

echo $line | awk -v var="$mycol_new" -F'\t' '{print $1 "," $2 "," var "," $4 "," $5 "," $6 "," $7 "," $8 "," $9 "}' >> /pdump/temp.txt

4
awk 'BEGIN {FS = "[\ t] +"}; {print $ 1} '# isto é o que eu estava procurando. Minha pesquisa no google está correta? :)
shantanuo

2
Graças a este comentário, descobri: awk 'BEGIN {FS="\t"}; {print $1,FS,$2,FS,$3}' myFile.txtimprimir valores delimitados por tabulação das três primeiras colunas.
Wok

6
Ou talvez simplesmenteawk 'BEGIN {OFS="\t"}; {print $1,$2,$3}'
Josiah Yoder

3
Ambos GNU e BSD awk suportam -vpara definir variáveis. É feio para usar BEGIN {FS="\t"}dentro de um programa embutido , e qualquer contribuição de código aberto que você tente fazer assim provavelmente será contestada. Faça isso apenas se estiver gravando um arquivo de programa . Além disso, é desencorajado usar em -Fvez de -v FS=porque o último deixa claro que apenas FSestá sendo definido e não OFS. A confusão sobre esse último ponto é o que causou esta postagem em primeiro lugar. É por isso que o "bom estilo" é importante.
Bruno Bronosky,

1
Por favor, ninguém, jamais, deve fazer o que @Wok demonstrou. Você não enumera separadores de campo [entrada] em sua saída. Você especifica um separador de campo de saída por meio da OFSvariável.
Bruno Bronosky,

Respostas:


138

Você precisa definir a OFSvariável (separador de campo de saída) para ser uma guia:

echo "$line" | 
awk -v var="$mycol_new" -F $'\t' 'BEGIN {OFS = FS} {$3 = var; print}'

(certifique-se de citar a $linevariável na instrução echo)


6
Qual é o propósito de $ em $ '\ t'?
Amr Mostafa

10
Respondendo minha própria pergunta do Advanced Bash Scripting Guide : A construção de expansão de string entre aspas $ '...' é um mecanismo que usa valores octais ou hexadecimais de escape ..., por exemplo, quote = $ '\ 042'.
Amr Mostafa

4
@AmrMostafa, muito ruim que o guia tem uma explicação enganosa levando a pensar que você não o $de $'\t'não é necessário. O wiki de Greg é melhor: "Destes, $'...'é o mais comum e atua como aspas simples, exceto que as combinações com escape de barra invertida são expandidas conforme especificado pelo padrão ANSI C".
Cristian Ciupitu

9
Em retrospectiva, o $'\t'não é necessário. awk entende a string "\t"como um caractere de tabulação
glenn jackman

5
Colaboradores de código aberto, eu imploro, por favor, não envie coisas como awk -F $'\t' 'BEGIN {OFS = FS} …'. Isso deveria ser awk -v FS='\t' -v OFS='\t' '…'. Pode parecer pedante, mas ser inconsistente aumenta as chances de que um colaborador posterior introduza um bug por interpretar mal seu código.
Bruno Bronosky,

21

Certifique-se de que são realmente guias! No bash, você pode inserir uma guia usandoC-v TAB

$ echo "LOAD_SETTLED    LOAD_INIT       2011-01-13 03:50:01" | awk -F$'\t' '{print $1}'
LOAD_SETTLED


8

Eu uso as variáveis FSe OFSpara manipular arquivos de zona BIND que são delimitados por tabulação. Aqui está um dos meus scripts https://gist.github.com/RichardBronosky/abe1652c2d5c78c35b92ad02bdf0d0af#file-dns_update-sh-L36-L39

A essência disso é:

awk -v FS='\t' -v OFS='\t' \
    -v record_type=$record_type \
    -v hostname=$hostname \
    -v ip_address=$ip_address '
$1==hostname && $3==record_type {$4=ip_address}
{print}
' $zone_file > $temp

Esta é uma maneira limpa e fácil de ler para fazer isso.


5
echo "LOAD_SETTLED    LOAD_INIT       2011-01-13 03:50:01" | awk -v var="test" 'BEGIN { FS = "[ \t]+" } ; { print $1 "\t" var "\t" $3 }'

0

Isso não deveria funcionar?

echo "LOAD_SETTLED    LOAD_INIT       2011-01-13 03:50:01" | awk '{print $1}'
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.