Кажется, вы хотите обрезать почтовые ящики для всех пользователей. Вы не можете сделать это, вызвав :
из find
, так как :
не является внешней утилитой (, это оболочка, встроенная -в утилиту ). Использование true
вместо :
сработало бы, так как это обычно доступно как внешняя команда, но...
Вы также не можете использовать перенаправление в команде, выполняемой через -exec
, так как это перенаправление будет задействовано оболочкой во время первого запуска утилиты find
(не один раз для каждого найденного файла ).
Ваша команда практически такая же, как
find /var/spool/mail/ -regextype sed -regex "^.*[^/]$" -exec : \; >{}
т. е. будет создан файл с именем {}
, в который перенаправляется стандартный поток вывода find
.
Вместо этого вы можете сделать что-то вроде
find /var/spool/mail -type f -exec sh -c '
for pathname do
: >"$pathname"
done' sh {} +
Как «один -лайнер»:
find /var/spool/mail -type f -exec sh -c 'for pathname do : >"$pathname"; done' sh {} +
Или, если все почтовые ящики находятся непосредственно под /var/spool/mail
,
for pathname in /var/spool/mail/*; do
: >"$pathname"
done
Как «один -лайнер»:
for pathname in /var/spool/mail/*; do : >"$pathname"; done
В обоих этих вариантах утилита :
вызывается правильно, и перенаправление будет происходить для каждого найденного имени пути (любого обычного файла в указанном пути поиска или ниже него ).
Похожие:
Создать счетчик в буфере (пространстве шаблонов )и проверять его на каждой строке:
sed '
/^line 1/{x;/11/!s/^/1/;x}
x;/11/{x;b1};x;b
:1;s/^line 3$/replaced/
' file
используем 1
в качестве счетчика
[обновление] Повышение производительности:
sed '
/^line 1$/{x;/11/!s/^/1/;x}
/^line 3$/!b
x;/11/!{x;b}
x;s/.*/replaced/
' file
Счетчик проверяется только в строках, соответствующих шаблону-/^line 3$/
Использование GNU sed
в частности:
sed -e '0,/^line 1$/ b' \
-e '//,$ s/^line 3$/replaced/' file
Сначала выводятся все строки между началом файла и первой строкой line 1
. Использование 0
в качестве начала диапазона адресов требует GNU sed
и позволяет нам справиться со случаем, когда line 1
является самой первой строкой файла.
Достигнув первой строки line 1
и выведя ее, он применяет замену ко всем строкам со следующей строки line 1
до конца файла, заменяя строки line 3
текстом replaced
.
Если вы хотите вставить несколько строк текста, используйтеc
(изменить ), а неs
(заменить):
sed -e '0,/^line 1$/ b' \
-e '//,$ {' \
-e '/^line 3$/ c\' \
-e 'replace 1\' \
-e 'replace 2' \
-e '}' file
Каждая строка, кроме последней, которой вы хотите заменить строки line 3
, должна заканчиваться обратной косой чертой.
Может быть проще увидеть, что делает этот sed
скрипт, если мы напишем скрипт как отдельный скрипт редактирования:
0,/^line 1$/ b
//,$ {
/^line 3$/ c\
replaced 1\
replaced 2
}
Используя ed
, мы могли бы найти первую line 1
, а затем выполнить командуc
(change )для каждой строки, соответствующей line 3
, начиная со следующей строки, соответствующей line 1
, и до конца.
/^line 1$/; //,$ g/^line 3$/ c\
replaced
Из командной строки, отправив результат на терминал,
ed -s file <<'END_ED'
/^line 1$/; //,$ g/^line 3$/ c\
replaced
,p
Q
END_ED
или,
printf '%s\n' '/^line 1$/; //,$ g/^line 3$/ c\' 'replaced' ',p' 'Q' |
ed -s file
Чтобы заменить строки line 3
несколькими строками текста, убедитесь, что каждая добавляемая строка текста завершается обратной косой чертой:
ed -s file <<'END_ED'
/^line 1$/; //,$ g/^line 3$/ c\
replaced\
more replace text\
even more
,p
Q
END_ED
Чтобы выполнить редактирование места -, используйтеw
(запись буфера в файл )иq
(выход )вместо,p
(печать всех строк в буфере )иQ
(выйти, безоговорочно )в сценарии редактирования.
Обратите внимание, что ed
не подходит для редактирования огромных файлов, так как редактор считывает файл в память.
Если вы хотите заменить строки одной строкой текста, вы можете избежать многострочного сценария -ed
, используяs
(замену )вместо c
(.нужны ,p
и Q
тоже):
/^line 1$/; //,$ g/^line 3$/ s//replaced/
Тестирование:
$ printf '%s\n' '/^line 1$/; //,$ g/^line 3$/ s//replaced/' ',p' 'Q' | ed -s file
line 1
line 2
line 3
line 1
line 2
replaced
line 1
line 2
replaced
С помощью GNU sed мы можем выполнить задачу путем сохранения счета в виде точек .
в трюме пространство.
sed -e '
/^line 1$/,/^line 1$/{//!b
x;s/^$/./;x;t
:a;n;s/^line 3$/REPLACED/;ba
}
' file
Другая возможность без использования диапазона оператор и с расширенным режимом регулярных выражений в GNU сед. Здесь символ новой строки \n
функционирует как счетчик, хранящийся в области удержания.
sed -Ee '
/^line 1$/H
x;s/^(\n{1,2}).*/\1/;x
/^line 3$/G
/\n.{2}/c REPLACED
s/\n//g
' file
Perl может сделать то же самое аналогичным образом
perl -lpe '
s/^line 3$/$a?"REPLACED":$&/e
unless
m?^line 1$?... /^line 1$(?{$a++})/;
' file
Используя awk, мы можем красиво комбинировать регулярные выражения с переменными и увеличением на единицу
awk '
1 < ( k += /^line 1$/ ) &&
sub(/^line 3$/,"REPLACED") ||
1' file