Когда оболочка доберется до оператора for
-, она расширит значение $search_dir
и выполнит подстановку имени файла, чтобы сгенерировать список записей каталога, которые будут повторяться. Это происходит только один раз, и если вещи в $search_dir
исчезнут или если в этот каталог будут добавлены новые файлы/каталоги во время выполнения цикла, эти изменения не будут приняты.
Если цикл работает с записями каталога, чьи имена находятся в $entry
, может потребоваться проверить их существование в цикле, особенно если известно, что цикл выполняется долго и имеется много файлов. которые находятся в постоянном движении по той или иной причине:
for entry in "$search_dir"/*; do
if [ -e "$entry" ]; then
# operate on "$entry"
else
# handle the case that "$entry" went away
fi
done
Как справедливо отмечает Стефан в комментариях, это лишний тест в большинстве случаев.
В чистом POSIX sed
вы должны вставить все строки самостоятельно. В то время как некоторые люди делают это с помощью N
внутри цикла, самый простой подход — добавить к пространству хранения шаблон H;1h;$!d;x
:
H
добавляет каждую строку в область хранения. К сожалению, добавление первой строки добавит новую строку в начало буфера, поэтому 1h
переопределит пробел для первой строки, чтобы избежать неправильного перехода на новую строку. $!d
завершит обработку всех строк, кроме последней. Их не нужно распечатывать,потому что они хранятся в резервном пространстве x
будет выполнено только после последней строки (для всех остальных строк d
остановит дальнейшую обработку команды )и x
изменит пространство удержания и пространство шаблона, поэтому после этой команды вся файл, который был собран в пространстве хранения, будет находиться в пространстве шаблонов, точно так же, как это было бы с опцией -z
GNU sed
. Конечно, вы также можете использовать g
вместо x
, но это приведет к большому количеству копирования, поэтому x
быстрее. Таким образом, скрипт для примера будет выглядеть так:
sed 'H;1h;$!d;x;s/\(.*\),/\1 and/'
Обратите внимание, что такая обработка файла не рекомендуется для очень больших файлов, так как при этом будет использоваться много оперативной памяти.
sed предназначен для выполнения простого s/old/new для отдельных строк, вот и все. Почти каждый раз, когда вы обнаруживаете, что используете конструкции, отличные от s, g и p (с -n ), и, конечно же, каждый раз, когда вы ловите себя на том, что говорите о «задержке пространства», вы используете неправильный инструмент. Для чего-то более сложного, чем s/old/new, как эта задача, вы должны просто использовать вместо этого awk. Следующее будет работать с использованием любого awk в любой оболочке на любом компьютере UNIX, не сохраняет весь файл в памяти и его легко настроить, если/когда вы хотите дополнительно сделать что-нибудь еще с текстом:
$ cat tst.awk
/,/ { printf "%s", prev; prev="" }
{ prev = prev $0 ORS }
END {
if ( match(prev,/.*,/) ) {
prev = substr(prev,1,RLENGTH-1) " and" substr(prev,RLENGTH+1)
}
printf "%s", prev
}
$ awk -f tst.awk file
yellow, green,
blue, black, purple,
orange,
white, red and brown
are some colours
Вы МОЖЕТЕ сделать эту работу короче в awk, запихнув весь файл в память и написав эту загадочную руну:
$ awk '{r=r$0 ORS} END{h=r;sub(/,[^,]+$/,"",h);sub(/.*,/,"",r);printf "%s and%s",h,r}' file
yellow, green,
blue, black, purple,
orange,
white, red and brown
are some colours
но дело в том, что, в отличие от sed, вам это не нужно.