Vincular variáveis entre dois arquivos de texto

3

A seguinte explicação é apenas uma representação do que eu gostaria de alcançar.

Eu tenho dois arquivos de texto: O primeiro arquivo de texto log1.txt contém as seguintes entradas:

Black
Blue
Brown
Copper
Cyan
Gold
Gray
Green

O segundo arquivo de texto log2.txt contém as seguintes entradas:

Ugly
Nice
cool
pretty

Eu gostaria de ler os dois textos ao mesmo tempo e gerar a seguinte saída:

The first color Black is Ugly
The second color Blue is Nice
The third color Brown is cool
The fourth color Copper is pretty
The fifth color Cyan is Ugly
The sixth color Gold is Nice
The seventh color Gray is cool
The eighth color Green is pretty

Como posso alcançar o resultado anterior usando bash ou shell ? Tentei aplicar dois loops ao mesmo tempo: for loop" and/or while loop 'mas não funcionou! Por exemplo, tentei este código desajeitado:

#!/bin/bash
while IFS= read -r line; do
    for ii in $(cat log1.txt); do

echo "The first color "$i "is" $ii

done <log2.txt
done

Eu não tenho ideia nem sei como mudar entre "primeira cor", "segunda cor",… .etc

    
por Rui F Ribeiro 07.09.2018 / 15:13

4 respostas

4

Com zsh e libnumbertext-tools ' spellout no Debian:

#! /bin/zsh -
colors=(${(f)"$(<log1.txt)"})
adjectives=(${(f)"$(head -n ${#colors} <log2.txt)"})

/usr/lib/libnumbertext/spellout -l /usr/share/libnumbertext/en \
  -p ordinal 1-$#colors |
for color adjective in ${colors:^^adjectives}; do
  read num &&
  print -r The $num color $color is $adjective
done

(note que é em inglês dos EUA. Por exemplo, para 101, você recebe cem em vez de cem e primeiro )

Se você não pode instalar o zsh ou qualquer software que soletre números, mas tenha uma lista de ordinais ingleses em um terceiro log3.txt , você poderia fazer na maioria dos shells incluindo bash (Bourne-like, rc como, peixe, pelo menos):

#! /bin/sh -
awk '
  BEGIN {while ((getline a < "log2.txt") > 0) adjective[na++] = a}
  {
    if ((getline num < "log3.txt") <= 0) num = NR "th"
    print "The "num" color "$0" is "adjective[(NR-1)%na]
  }' log1.txt

(voltando a <digits>th se ficarmos sem números em inglês).

    
por 07.09.2018 / 15:42
1

Seu shell não sabe inglês, portanto, gerar automaticamente os números com sufixos corretos para uma contagem arbitrária envolveria algum esforço adicional. Com apenas dígitos para a numeração e a presunção adicional de que log1.txt é o arquivo mais longo, tente isto:

#!/bin/bash
log1_length=$(wc -l <log1.txt)
log2_length=$(wc -l <log2.txt)

for i in $(seq $log1_length); do
    arg1=$(head -$i <log1.txt | tail -1)
    arg2=$(head -$(((i-1) % log2_length + 1)) <log2.txt | tail -1)
    echo "Color No. $i $arg1 is $arg2."
done
    
por 07.09.2018 / 15:56
1

Você pode conseguir o que quiser usando estrutura de controle de caso da seguinte forma:

#!/bin/bash
log1_length=$(wc -l <log1.txt)
log2_length=$(wc -l <log2.txt)

for i in $(seq $log1_length); do 
    arg1="$(head -$i <log1.txt | tail -1)"
    arg2="$(head -$(((i-1) % log2_length + 1)) <log2.txt | tail -1)"
   # Case control structure to replace digit equivalent in words 
    case ${i} in
        1) echo -n "The first color ";;
        2) echo -n "The second color ";;
        3) echo -n "The third color ";;
        4) echo -n "The fourth color ";;
        5) echo -n "The fifth color ";;
        6) echo -n "The sixth color ";;
        7) echo -n "The seventh color ";;
        8) echo -n "The eighth color ";;
        9) echo -n "The ninth color ";;
       10) echo -n "The tenth color ";;
       11) echo -n "The eleventh color ";;
    esac 
    echo ${i}"$i${arg1} is ${arg2}" |  tr -d '0123456789'   
done

A saída é a seguinte:

The first color Black is Ugly
The second color Blue is Nice
The third color Brown is cool
The fourth color Copper is pretty
The fifth color Cyan is Ugly
The sixth color Gold is Nice
The seventh color Gray is cool
The eighth color Green is pretty
    
por 07.09.2018 / 16:19
0

Estou surpreso que ninguém tenha sugerido o uso de matrizes. Aqui está minha tentativa grosseira (usando a idéia de log3.txt de @Stephane acima.

#!/bin/bash

nl1=$( wc -l < log1.txt )
nl2=$( wc -l < log2.txt )
nlnums=$( wc -l < nums.txt )

declare -a arr1[$nl1]
declare -a arr2[$nl2]
declare -a nums[$nlnums]

for (( i=0; i < $nl1; i++ ))
do
    read arr1[$i]
done < log1.txt

for (( i=0; i < $nl2; i++ ))
do
    read arr2[$i]
done < log2.txt

for (( i=0; i < $nlnums; i++ ))
do
    read nums[$i]
done < nums.txt

j=0
for (( i=0; i < $nl1; i++ ))
do
    echo "The ${nums[$i]} color ${arr1[$i]} is ${arr2[$j]}"
    j=$(( (j+1) % $nl2 ))
done

O arquivo nums.txt é o seguinte:

first
second
third
fourth
fifth
sixth
seventh
eighth
ninth
tenth

O código precisa ser limpo um pouco, mas ilustra o ponto.

    
por 08.09.2018 / 00:32