Как я могу "тройник" переменное число раз в bash "для цикла"?
Я понимаю, что могу:
ssh archive_server -l user -n "cat text.csv"|tee -a text1.csv|tee -a text2.csv|tee....|tee -a text10.csv
Есть ли способ сделать это в виде петли?
for i in `seq 1 10`; do
echo $i
tee ???
done
2 ответа
Вам не нужна петля. tee
может быть задано несколько аргументов имени файла, поэтому просто укажите все выходные файлы:
cat text.csv | tee -a text{1..10}.csv
Если количество файлов является динамическим, вы можете использовать цикл в $()
вставить имена файлов в командную строку:
cat text.csv | tee -a $(
for i in $(seq 1 $filecount); do
echo text$i;
done)
Просто убедитесь, что в префиксе выходного имени файла нет пробелов, так как эти пробелы будут рассматриваться как разделители аргументов.
Предполагая, что ваша оболочка действительно bash (не /bin/sh
), вы можете построить массив (и использовать стиль C for
цикл, который в отличие от нестандартной внешней команды seq
, гарантированно будет доступен везде, где есть bash):
#!/bin/bash
filenames=( )
for ((i=1; i<=10; i++)); do # note that the "10" here can be a variable name
filenames+=( "file$i.txt" )
done
tee -a -- "${filenames[@]}" <text.csv
Если вам нужна совместимость с /bin/sh
, это становится немного более многословным:
#!/bin/sh
tee_between() (
prefix=$1; suffix=$2; start=$3; end=$4
set --
i=$(( $start - 1 )); while [ $(( ( i += 1 ) <= end )) -ne 0 ]; do
set -- "$@" "file$i.txt"
done
exec tee -a -- "$@"
)
tee_between "file" ".txt" 1 10 <text.csv
Замечания:
set --
изменяет список аргументов текущего процесса (или, в данном случае, текущей функции), используя его в качестве массива, который мы можем динамически изменять.tee_between() ( )
вместоtee_between() { }
означает, что функция выполняется в подоболочке - это совершенно отдельный раздвоенный процесс. В результате этого выбораexec
Команда заменит только эту подоболочку с копиейtee
а не родительский процесс.