Eu tenho um arquivo de controle - cntl.txt
2
3
5
Arquivo de dados - data.txt
red
blue
yellow
green
violet
orange
Preciso ler as linhas correspondentes do arquivo de controle, aqui a saída esperada é:
blue
yellow
violet
Responder1
Exemplo de uma solução muito ineficiente:
for i in $(<control.txt); do awk -v c=$i 'NR~c{ print $0 }' data.txt; done;
Relato também uma boa solução que aprendi esta noite:
awk 'FNR==NR{ z[$0]++;next }; FNR in z' control.txt data.txt
Responder2
Usando apenasPOSIX especificadocaracterísticas do Sed:
sed -n -e "$(sed '/./s/$/p/' cntl.txt)" data.txt
É claro que se o seu cntl.txt
arquivo tiver linhas além de números, você poderá receber um erro. Mas se tiver linhas vazias estas serão tratadas corretamente (ou seja, não afetarão a saída).
Responder3
Experimente isto:
join <(nl data.txt|sort -k1b,1) <(cat cntl.txt|sort -k1b,1) | sort -nk1,1 | cut -d' ' -f2-
nl - enumerará linhas para você
1 red
2 blue
3 yellow
4 green
5 violet
6 orange
| sort -k1b,1 - irá classificá-los pelo número da linha (primeiro campo), lexicograficamente
gato cntl.txt| sort -k1b,1 - classificará o arquivo de controle na mesma ordem
2
3
5
join <() <() - juntará os "dados" classificados (e numerados) com o "controle" classificado, no primeiro campo (ou seja, número da linha)
2 blue
3 yellow
5 violet
|sort -nk1,1 - reordenará os resultados numericamente (para colocar as linhas novamente em ordem)
| cut -d' ' -f2- - eliminará o campo do número da linha
blue
yellow
violet
Responder4
Outra solução possível:
IFS=$'\n' read -d '' -r -a colors < 'data.txt'; unset IFS;
for i in $(<cntl.txt); do
echo ${colors[i-1]}
done
A linha IFS configura o separador de arquivo interno como nova linha e insere cada linha de data.txt no array. Depois disso, você percorre as linhas em cntl.txt e imprime os elementos da matriz com determinado índice (menos 1 porque você inicia seu data.txt a partir de 1, não de 0, caso contrário, seria desnecessário).