loop através de um arquivo de duas colunas

0

A minha pergunta é basicamente uma pergunta de seguimento em este tópico . Eu tenho um arquivo como este:

1000 | line1
100  | line2
10   | line3

Eu quero fazer algo em $ 2 se $ 1 for maior que 20. Eu escrevi algo para imitar a segunda resposta mas não funciona:

for a, b in $(cat file.text|cut -d"|" -f 1,2);
do
if ($1>20) echo $2
done;

Como posso conseguir isso? Obrigado!

    
por user3768495 04.05.2018 / 19:32

5 respostas

1
awk -F'|' '$1 > 20 { system("/path/to/another/script.sh "$2 }' < file.text

Isto diz ao awk para dividir a entrada em campos baseados no símbolo do pipe. Qualquer primeiro campo cujo valor seja maior que 20 aciona a chamada do sistema para ... o que você quiser. Tenha em mente que o argumento (aqui $ 2, mas poderia ser $ 0 ou qualquer outro cálculo feito no awk) é passado para o script por meio de uma chamada de shell, portanto, se esses valores puderem conter caracteres especiais do shell, cite-o cuidadosamente. Vou me referir a uma das respostas de Stéphane para um exemplo de como fazer isso:

awk 'function escape(s) {
       gsub(/'\''/,"&\\&&",s)
       return "'\''" s "'\''"
     }
     { system("/path/to/another/script.sh" escape($2)) }'
    
por 04.05.2018 / 20:03
2

com awk :

$ for param in $(awk '$1 > 20 { print $3 }' inputfile); do ./process.sh "$param"; done
    
por 04.05.2018 / 19:51
2

Você não deseja realmente analisar dados no próprio shell, mas usar uma ferramenta como awk para fazer isso por você.

awk -F '[[:blank:]|]+' '$1 > 20 { print $2 }' file

Isso instrui awk a tratar cada linha do arquivo como um conjunto de campos delimitados por qualquer número de símbolos de pipe ou espaços em branco (espaços ou tabulações). Quando o primeiro campo é maior que 20, o segundo campo é impresso.

Relacionados:

Se a segunda coluna contiver espaços em branco, convém usar [[:blank:]]*[|][[:blank:]]* como delimitador:

awk -F '[[:blank:]]*[|][[:blank:]]*' '$1 > 20 { print $2 }' file

O [|] corresponde a um símbolo de pipe literal e pode ser substituído por \| (se você gosta de barras invertidas).

O seguinte executa um script com cada instância da segunda coluna cuja primeira coluna é maior que 20 como o argumento da linha de comando:

awk -F '[[:blank:]]*[|][[:blank:]]*' '$1 > 20 { print $2 }' file |
xargs -I XX ./script.sh XX

Com algo como -P 4 como uma opção para xargs , você pode executar várias instâncias paralelas do seu script de uma só vez (quatro com -P 4 ).

    
por 04.05.2018 / 20:00
0

Eu consegui fazer isso com o seguinte:

#!/bin/bash
while read -r col1 col2 col3 trash; do
    [[ "$col2" == '|' && "$col1" -gt 20 ]] && echo "$col3"
done<file.text

Isso lerá cada linha do arquivo e definirá cada coluna para as variáveis col1 , col2 e col3 , respectivamente. Tudo o que sobrar será atribuído à variável trash . Em seguida, ele verifica se col2 é igual a | e que col1 é maior que 20. Se os dois forem verdade, será impresso col3 .

    
por 04.05.2018 / 19:46
0

Você pode tentar com o gnu sed também

sed -E 's/([0-9]*) \| (.*)/[  -gt 20 ] \&\& echo do something with /e' infile
    
por 04.05.2018 / 22:37