#linux #redirect #sed #xargs
#linux #перенаправление #sed #xargs
Вопрос:
После перехода на более совершенную систему управления я хочу удалить все избыточные журналы в верхней части каждого из наших исходных файлов. В Notepad я смог добиться результата, используя «заменить в файлах» и заменив совпадения на A(//.*n)
пустые. Однако в Linux мне не повезло, и мне нужно прибегнуть к «xargs» и «sed».
Выражение sed, которое я использую, является:
sed '1,/^[^/]/{/^[^/]/b; d}'
Конечно, некрасиво, но, похоже, это работает.
Проблема, с которой я сталкиваюсь, заключается в том, что когда я пытаюсь запустить это через «xargs», чтобы передать ему все исходные файлы в нашей системе, я не могу перенаправить вывод на «удаленные» файлы, которые я затем намереваюсь скопировать поверх оригиналов.
Я хочу что-то в строке:
find . -name "*.com" -type f -print0 | xargs -0 -I file sed '1,/^[^/]/{/^[^/]/b; d}' "file" > "file.stripped"
Однако у меня возникают проблемы с передачей «>» в принимающую среду (оболочку), поскольку я уже использую слишком много кавычек. Я перепробовал все способы экранирования и оболочки «оболочки», но я просто не могу заставить его играть в мяч.
Кто-нибудь хочет указать мне правильное направление?
Спасибо, Сларти.
Комментарии:
1. Поддерживает ли ваша реализация sed
-i
эту опцию?2. Есть, да, это так. Это делает жизнь намного проще. Я попробую и вернусь к вам 😉
3. Почему вы должны использовать опцию -exec в find. Что-то похожее на это,
find . -name "*.com" -type f -print0 -exec sed '1,/^[^/]/{/^[^/]/b; d}' {} > "file.stripped" ;
4. Я попытался использовать опцию find «-exec», но также не смог заставить ее работать. Как бы то ни было, мне потребовалось так много времени, чтобы сформулировать вопрос с помощью моего телефона, что офис резко закрылся, и мне пришлось уйти, прежде чем пытаться выполнить какое-либо из этих предложений, но я полагаю, что ваше предложение либо добавит все в файл, буквально называемый «file.stripped», либо постоянно перезаписывает один и тот же файл любым текущимв то время была версия pc «{}». Обратите внимание, что замена «file.stripped» на «{}.stripped» также не работает, он просто создает файл с именем «{}.stripped».
Ответ №1:
Я сделал аналогичный сценарий с более простым выражением sed просто в качестве примера, посмотрите, работает ли он для вас:
Я создал 3 файла со строкой «abcd» внутри каждого:
# ls -l
total 12
-rw-r--r-- 1 root root 5 Oct 6 09:05 test.aaaaa.com
-rw-r--r-- 1 root root 5 Oct 6 09:05 test2.aaaaa.com
-rw-r--r-- 1 root root 5 Oct 6 09:05 test3.aaaaa.com
# cat test*
abcd
abcd
abcd
Запуск команды find, как вы показали, с использованием опции -exec вместо xargs и замена выражения sed на глупое, которое просто заменяет каждое «a» на «b» и параметр -i, который записывает непосредственно во входной файл:
# find . -name "*.com" -type f -print0 -exec sed -i 's/a/b/g' {} ;
./test2.aaaaa.com./test3.aaaaa.com./test.aaaaa.com
# cat test*
bbcd
bbcd
bbcd
В вашем случае это должно выглядеть так:
# find . -name "*.com" -type f -print0 -exec sed -i '1,/^[^/]/{/^[^/]/b; d}' {} ;
Комментарии:
1. Спасибо. Это действительно сработало отлично. Из полноты, однако, есть идеи, как можно перенаправить вывод?
2. Этого нельзя достичь с помощью опции xargs -I, потому что после знака «>», используемого для перенаправления вывода, он понимает, что он больше не является частью аргументов команды, поэтому он не заменяет «file.stripped» на фактическое имя файла, которое вам дает «find», и в итоге создаетбуквальный файл «file.stripped». Для достижения этой цели вы могли бы написать скрипт, используя команду «for» в сочетании с «find» и «xargs», но это не самый умный и не самый простой способ сделать это. Кроме того, не забудьте поддержать мой ответ. 😉 Приветствия!