Создание нескольких входных файлов при помощи sed в для цикла

Мое решение.

+ vs \; в команде -exec

                    
2
21.08.2018, 05:47
2 ответа

Шелловые скрипты содержат множество литературных строк (имена команд, файлов и т.д.), поэтому использование значения переменной требует символа для явной пометки, что это ссылка на переменную: Расширение параметра состоит из $, за которым следует имя переменной (в самом простом виде). Обычно вокруг подстановки переменной нужны двойные кавычки. Внутри одиночных кавычек переменные вообще не расширяются ($ внутри '...' просто обозначает себя). Таким образом:

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

Оператор перенаправления >> присоединяется к существующему файлу, в отличие от > , который усекает файл, если он существует.

1
27.01.2020, 22:12

Я думаю, что было бы ошибкой вызывать столько 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 ...

  1. Перезаписать его h старый буфер с копией его буфера редактирования.
  2. g lobally s /// ub заменить каждое вхождение буквы a в буфер редактирования любым текущим значением переменной оболочки $ a .
  3. При этом оба p записывают результаты этого s /// ubstitution в стандартный вывод и w записывают результаты в файл с именем / tmp / $ am , где $ a - итерация.
  4. И наконец, 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
1
27.01.2020, 22:12

Теги

Похожие вопросы