Есть ли способ одновременно использовать две разные ссылки на файлы в циклах for? Что-то типа:
for file in file1 file2 file3; for name in name1 name2 name3
do
awk 'FNR==NR{a[$1];next};($1 in a)' ${file}.txt ${name}.txt > ${name}_extract.txt
done
Я также пробовал с вложенным циклом for, который не работал:
for file in file1 file2 file3
do
for name in name1 name2 name3
do
awk 'FNR==NR{a[$1];next};($1 in a)' ${file}.txt ${name}.txt > ${name}_extract.txt
done
done
Чего я хотел бы добиться, так это извлечь строки из «file1.txt» и «name1.txt», которые соответствуют их первому столбцу. И наоборот для файла2.txt/имя2.txt и файла3.txt/имя3.txt.
В будущем, когда у вас будет ошибка сценария оболочки, хорошим первым шагом будет вырезать и вставить ваш код в shellcheck.net и исправить ошибки (важные) и предупреждения (могут быть важными), которые он идентифицирует. Если у вас есть проблемы с пониманием его сообщений, зайдите сюда и спросите.
@John1024 John1024 Да, я пропустил одно утверждение do
, хотя оно все еще не работает, см. редактирование. Он не выдает ошибок, но все выходные файлы, кроме одного, пусты.
Вы пытаетесь перебрать все комбинации переменных (например, «файл1» и «имя1», затем «файл1» и «имя2», затем «файл1» и «имя3», затем «файл2» и «имя1» и т. д.) или сразу над соответствующими элементами (т.е. просто «файл1» и «имя1», затем «файл2» и «имя2», затем «файл3» и «имя3»)? Две петли дадут вам все комбинации; если вам нужны только соответствующие элементы, вам нужен один цикл (и, возможно, элементы в массивах).
Если файлы и имена действительно называются file1
, file2
, file3
и name1
, name2
и name3
, то можно сделать примерно так:
for i in {1..3}; do
printf '%s\n' "file: file$i, name: name$i"
done
Вы заменяете оператор printf
тем, что вам нужно — важная часть — это то, как вы получаете доступ к файлам и именам.
Однако, если они имеют произвольные имена, вам нужно сделать что-то вроде подготовки двух массивов, а затем выполнить цикл по индексам:
files=(file1 file2 file3)
names=(name1 name2 name3)
for (( i = 0; i < ${#files[@]}; ++i )); do
printf '%s\n' "file: ${files[i]}, name: ${names[i]}"
done
Из вопроса неясно, хотите ли вы запустить 3 итерации или 9. Если вы хотите только 3 итерации, мне нравится формат:
while read file name; do
...
done << EOF
file1 name1
file2 name2
file3 name3
EOF
Отлично, спасибо @William Pursell, это прекрасно работает!
Для двух циклов
for
требуются операторы дваdo
. Вам не хватает одного.