Как читать содержимое из двух файлов и объединяться в 3-й файл в оболочке bash
как Вы читаете / обрабатываете 2 файла в синхронизации друг с другом в bash?
у меня есть 2 текстовых файла, которые имеют одинаковое количество строк/элементов в них. Один файл
a
b
c
другой файл
1
2
3
как мне перебрать эти файлы в синхронизации, так что a
связан с 1
, b - >2, c->3?
Я думал, что могу читать файлы в виде массива, а затем обрабатывать их с помощью индекса, но похоже, что мой синтаксис / логика неправильный.
этом f1=$(cat file1)
делает f1 = a b c
. Я думал делать f1=($(cat file1))
сделал бы его в массив, но он делает f1=a
и, таким образом, нет массива для обработки.
в случае, если кому-то было интересно, что мой испорченный код:
hostnames=($(cat $host_file))
# trying to read in as an array, which apparently is incorrect
roles=($(cat $role_file))
for i in {0..3}
do
echo ${hostnames[$i]}
# wanted to iterate through each element in the file/array
# but there is only one object instead of N objects
echo ${roles[$i]}
done
7 ответов
использовать paste
(ссылка), чтобы объединить файлы, а затем обработать одну строку объединенного файла за раз:
paste file1 file2 |
while read -r first second
do
echo $first
echo $second
done
можно использовать файловые дескрипторы:
while read -r var_from_file1 && read -r var_from_file2 <&3; do
echo "$var_from_file1 ---> $var_from_file2"
done <file1 3<file2
выход:
a ---> 1
b ---> 2
c ---> 3
код для GNU sed:
-
С
file1
перед:sed -r 's#(.*)#s/(.*)/ \1/;$!n#' file1|sed -rf - file2
или
-
С
file2
перед:sed -r 's#(.*)#s/(.*)/\1 /;$!n#' file2|sed -rf - file1
оба вывода приводят к одному и тому же выводу:
a 1 b 2 c 3 d 4 e 5 f 6 g 7
два примера с awk:
awk '{print , NR}' file1
и - гораздо лучше :-)
awk 'NR==FNR {a[NR]=;next};{print a[FNR], }' file1 file2
..выход всегда есть:
a 1
b 2
c 3
ваш путь:
host_file=host1
role_file=role1
hostnames=( $(cat $host_file) )
roles=( $(cat $role_file) )
(( cnt = ${#hostnames[@]} -1 ))
echo "cnt is $cnt"
for (( i=0;i<=$cnt;i++))
do
echo "${hostnames[$i]} -> ${roles[$i]}"
done
сжатым и гибким решением этой проблемы является core-util pr
:
# space separated
$ pr -mts' ' file1 file2
a 1
b 2
c 3
# -> separated
$ pr -mts' -> ' file1 file2
a -> 1
b -> 2
c -> 3
посмотреть man pr
для получения дополнительной информации.
Чисто Баш:
IFS=$'\n'
hostnames=( $( <hostnames.txt ) )
roles=( $( <roles.txt ) )
for idx in ${!hostnames[@]}; do # loop over array indices
echo -e "${hostnames[idx]} ${roles[idx]}"
done
или после комментария gniourf_gniourf
mapfile -t hostnames < hostnames.txt
mapfile -t roles < roles.txt
for idx in ${!hostnames[@]}; do # loop over array indices
echo -e "'${hostnames[idx]}' '${roles[idx]}'"
done