Update далеко лучшая версия Баш кода добавлен. Благодаря Charles Duffy для комментариев.
Ваш Perl один вкладыш занимает линию по трубам в него echo $p |
, получая свой стандартный ввод таким образом. Он ничего не делает с самим файлом, поэтому флаг -i
не влияет. -p
делает печать стандартным потоком вывода. Так что вся строка, echo ...
, не касается файла.
Вы можете перенаправить вывод на новый файл, а затем переместить его, чтобы перезаписать file.txt
. Вот простой пример, который добавляет каждую строку в новый файл. Для лучшего кода bash см. Обновление ниже.
while read p; do
if condition
then
echo $p | perl -pe 's/a/b/' >> temp_out.txt
else
echo $p >> temp_out.txt
fi
done < file.txt
mv temp_out.txt file.txt
Мы должны добавить else
где все неизмененные строки также добавляется. Обратите внимание, что в общем случае мы не можем заменить только некоторые строки, но весь файл должен быть переписан.
Если это все, что сценарий вы можете сделать с помощью очень простой однострочной линии, см. Конец. Если больше работы сделано, вы также можете поместить все это в скрипт Perl, но я полагаю, что могут быть другие веские причины для сценария bash.
Update Гораздо лучше вариант выше. См read
и echo
в Builtins in Bash manual
прилагая каждую строку открывает файл заново каждый раз без необходимости. Просто переадресовать в конце цикла, как это делается в терминале
read
использует обратную косую черту для экранирования, удаляя ее из ввода. Выключите это с помощью -r
Удаляет пустое пространство, как часть разрыва строки в слова. Подавляйте это, отключая переменную, которая контролирует, какие символы используются для разделения, IFS=
echo $p
может делать всевозможные непреднамеренные вещи.Форматированная печать лучше, printf '%s\n' "$p"
, или по крайней мере echo "$p"
С этим
while IFS= read -r p; do
if condition
then
echo "$p" | perl -pe 's/a/b/'
else
echo "$p"
fi
done <file.txt> temp_out.txt
mv temp_out.txt file.txt
Наконец, если единственной целью Perl однострочника были запустить простую замену, то гораздо лучше просто сделать это в самой оболочке, чем иметь конвейер и запустить совершенно новый процесс для каждой строки.
echo "${p//a/b}"
Благодаря Charles Duffy для поднятия всех этих пунктов в комментариях.
Несколько комментариев на Perl однострочные. См. Документацию по адресу perlrun
.
Команда perl -e '...'
выполняет любой действующий код Perl между ''
. Когда мы добавляем переключатель -n
или -p
, он также считывает стандартный ввод и выполняет этот код по его строке в то время, когда -p
также распечатывает каждую строку после ее обработки. Стандартный ввод может подаваться в него из файла,
perl -pe '...' input.txt
в этом случае при добавлении -i
флага приведет к файлу изменяется на месте. Или вход может быть подключен к нему, например,
echo "input text" | perl -pe '...'
В этом случае обрабатываемая линия печатается на стандартный выход. Это можно перенаправить в файл, как в ответе выше.
Чтобы внести изменения в данный файл очереди в то время, вам нужно только это в командной строке
perl -i -pe 's/a/b/' file.txt
Если есть больше работы, чтобы сделать то, что вполне может быть лучше положить его в сценарии, конечно. В этом случае однострочный может быть также командой в сценарии bash, заменяя весь этот код выше (если для обработки строк не требуется некоторая функция, специфичная для bash).
все средства обработки текста могут читать файл по строкам и обрабатывать, нет необходимости привлекать петли bash для этого. – karakfa
Согласитесь с @karakfa: Знаете ли вы, что 'sed -i 's/a/b /' file' может обрабатывать весь файл одновременно, намного эффективнее и (очевидно) имеет намного меньше кода? Удачи. – shellter
Если вы хотите отредактировать файл, почему бы вам не использовать редактор? 'ex' и' ed' приходят на ум ... –