Шелловые скрипты содержат множество литературных строк (имена команд, файлов и т.д.), поэтому использование значения переменной требует символа для явной пометки, что это ссылка на переменную: Расширение параметра состоит из $
, за которым следует имя переменной (в самом простом виде). Обычно вокруг подстановки переменной нужны двойные кавычки. Внутри одиночных кавычек переменные вообще не расширяются ($
внутри '...'
просто обозначает себя). Таким образом:
for ((i=1; i<=10; i++)); do
sed "s/a/$i/" <a.m >"$i.m"
done
Внутри двойных круглых скобок знаки доллара не нужны, так как двойные скобки разделяют арифметические выражения, а в арифметических выражениях нет строк, поэтому голое слово интерпретируется как переменная, на которую можно разыменовать ссылку.
Обратите внимание, что команда sed заменяет самый первый a
символ в файле-шаблоне. Вы можете захотеть выбрать имя переменной, которое имеет меньше шансов появиться в чем-то другом, например, в имени функции. В качестве альтернативы можно сгенерировать присваивание в начале скрипта:
for ((i=1; i<=10; i++)); do
echo "a=$i;" >"$i.m"
cat a.m >>"$i.m"
done
Оператор перенаправления >>
присоединяется к существующему файлу, в отличие от >
, который усекает файл, если он существует.
Я думаю, что было бы ошибкой вызывать столько sed
, где подойдет только один. sed
славится своей способностью эффективно перебирать входные данные и преобразовывать их в разные выходные, но он также может очень легко обрабатывать несколько выходов. Вот, например, переносимая POSIX (и гораздо более эффективная) перезапись вашего цикла for
:
echo "Solve[x^2+5^a==$((a=0)),x]>>a.out" >/tmp/i.m ###create file + init $a
until [ "$((a+=1))" -gt 10 ] ###iterate + test
do printf "h;s/a/$a/gpw /tmp/$a.m\ng;" ###push new sed command
done| sed -nf - /tmp/i.m ###read + apply commands
head /tmp/[0-9].m /tmp/10.m ###print results
sed
может прочитать свой сценарий из стандартного ввода и применить его к именованный файл - это то, что делает приведенный выше оператор sed -nf - / tmp / im
. Он также может одновременно p
записать свой вывод в stdout и w
записать его вывод в один или несколько именованных файлов. По мере того, как цикл оболочки работает, он печатает строки в sed
, которые по завершении составляют:
h;s/a/1/gpw /tmp/1.m
g;h;s/a/2/gpw /tmp/2.m
g;h;s/a/3/gpw /tmp/3.m
g;h;s/a/4/gpw /tmp/4.m
g;h;s/a/5/gpw /tmp/5.m
g;h;s/a/6/gpw /tmp/6.m
g;h;s/a/7/gpw /tmp/7.m
g;h;s/a/8/gpw /tmp/8.m
g;h;s/a/9/gpw /tmp/9.m
g;h;s/a/10/gpw /tmp/10.m
g
Что сообщает sed
...
h
старый буфер с копией его буфера редактирования. g
lobally s ///
ub заменить каждое вхождение буквы a
в буфер редактирования любым текущим значением переменной оболочки $ a
. p
записывают результаты этого s ///
ubstitution в стандартный вывод и w
записывают результаты в файл с именем / tmp / $ am
, где $ a
- итерация. g
очистить буфер хранения путем перезаписи буфера редактирования. sed
применит эту последовательность для каждой строки в названном входном файле.При первом вызове он усекает каждый из своих именованных файлов обряда w
, но после этого добавляет каждое действие обряда w
в каждый выходной файл по очереди. Поскольку у меня есть только одна строка в im
, sed
печатает:
Solve[x^2+5^1==0,x]>>1.out
Solve[x^2+5^2==0,x]>>2.out
Solve[x^2+5^3==0,x]>>3.out
Solve[x^2+5^4==0,x]>>4.out
Solve[x^2+5^5==0,x]>>5.out
Solve[x^2+5^6==0,x]>>6.out
Solve[x^2+5^7==0,x]>>7.out
Solve[x^2+5^8==0,x]>>8.out
Solve[x^2+5^9==0,x]>>9.out
Solve[x^2+5^10==0,x]>>10.out
и head
, считывая из каждого из десяти вновь созданных файлов в / tmp
, выводит:
==> /tmp/1.m <==
Solve[x^2+5^1==0,x]>>1.out
==> /tmp/2.m <==
Solve[x^2+5^2==0,x]>>2.out
==> /tmp/3.m <==
Solve[x^2+5^3==0,x]>>3.out
==> /tmp/4.m <==
Solve[x^2+5^4==0,x]>>4.out
==> /tmp/5.m <==
Solve[x^2+5^5==0,x]>>5.out
==> /tmp/6.m <==
Solve[x^2+5^6==0,x]>>6.out
==> /tmp/7.m <==
Solve[x^2+5^7==0,x]>>7.out
==> /tmp/8.m <==
Solve[x^2+5^8==0,x]>>8.out
==> /tmp/9.m <==
Solve[x^2+5^9==0,x]>>9.out
==> /tmp/10.m <==
Solve[x^2+5^10==0,x]>>10.out