Usando uma "declaração for" para simplificar a declaração bash com repetições múltiplas

3

Estou criando um nome de arquivo via grep e concatenando os arquivos resultantes com cat . No entanto, ainda estou um pouco confuso sobre como devo usar a declaração for, por exemplo for ((i=1;i<23;i+=1));

Dado meu arquivo file1.txt , gostaria de grep sample1 da seguinte forma:

grep -w '^sample1' file1.txt > sample1_file.txt
grep -w '^sample2' file2.txt > sample2_file.txt
grep -w '^sample3' file3.txt > sample3_file.txt
....
grep -w '^sample22' file22.txt > sample22_file.txt

Em seguida, concatene-os:

cat  sample1_file.txt  sample2_file.txt  sample3_file.txt ...  sample22_file.txt > final_output.txt
    
por EB2127 29.12.2017 / 23:00

3 respostas

8

Tente:

for i in {1..22}
do
    grep -w "^sample$i" "file$i.txt"
done >final_output.txt

Notas:

  1. {1..22} é executado em todos os inteiros de 1 a 22. Para pessoas não familiarizadas com C, é provavelmente mais intuitivo (mas menos flexível) do que ((i=1;i<23;i+=1))

  2. É importante que a expressão ^sample$i esteja entre aspas duplas, em vez de aspas simples, de forma que o shell expanda $i .

  3. Se tudo que você quer é final_output.txt , não há necessidade de criar os arquivos intermediários.

  4. Observe que é eficiente colocar o redirecionamento para final_output.txt após a instrução done : desta forma, o shell precisa abrir e fechar este arquivo apenas uma vez.

por 29.12.2017 / 23:04
2

Você parâmetros e variáveis de referência com o cifrão , portanto o contador de loop i pode ser usado como $i dentro do loop (entre aspas duplas, não aspas simples). Então você só precisa das palavras-chave do e done para iniciar e finalizar a parte maluca .

Então, a conversão direta:

> final_output.txt
for (( i = 1 ; i < 23 ; i += 1)); do
    grep -w "^sample$i" "file$i.txt" > "sample${i}_file.txt"
    cat "sample${i}_file.txt" >> final_output.txt
done

O uso das aspas em torno de "file${i}.txt" não é estritamente necessário, contanto que i contenha apenas um número, mas é um bom hábito citar quaisquer referências de variáveis, por vários motivos.

Observe que, no caso de sample${i}_file.txt , precisamos das chaves em ${i} , pois o sublinhado é válido em um nome de variável, e a gravação de $i_file.txt se referiria à variável i_file .

O% inicial > final_output.txt é para limpar o arquivo no início, já que o anexamos dentro do loop. Naturalmente, você pode simplesmente ignorar a criação dos arquivos sample1_file.txt , se não precisar deles, e apenas grep ... >> final_output.txt .

Como alternativa, você pode usar expansão de contraventamento para gerar uma lista dos números, em vez de contar manualmente com o loop for (( ... )) , ou seja, for i in {1..22}; do ... done .

Ou, no shell POSIX padrão:

i=1
while [ "$i" -lt 23 ] ; do
    grep ...
    i=$((i + 1))
done
    
por 29.12.2017 / 23:11
2

Uso:

#/bin/bash
:>final_output.txt
for i in {1..22}; do
    a=file"$i".txt
    b=sample"$i"_file.txt

    grep -w '^sample'"$i" "$a" > "$b"
    cat "$b" >> final_output.txt
done

A linha :>final_output limpa o arquivo para 0 bytes.
A "expansão da chave" {1..22} expande-se para a lista de números 1 2 3… 22.
A linha for i in {1..22}; do faz um loop sobre todos os números 1… 22.
O "Anexar" ( >> ) é necessário, pois queremos armazenar todas as saídas para o arquivo.

    
por 29.12.2017 / 23:19