sed remove строку после шаблона и добавить новую строку в этот интервал

Suponiendo que desea buscar todos los archivos .zipen o debajo del directorio actual y verificar si hay algo con el mismo nombre pero sin el sufijo de nombre de archivo .zip:

find. -type f -iname '*.zip' -exec sh -c '
    for a do
        n="${a%.zip}"
        [ -e "$n" ] && printf "%s\n" "$n"
    done' sh {} +

Con un directorio que contiene

file
file.zip
file2.zip
file3
file3.zip

el comando anterior generaría

./file
./file3

Esto se hace buscando todos los archivos .zipy, para todos los archivos encontrados, ejecute un breve script de shell que elimine la extensión de cada nombre y verifique si ese nuevo nombre existe o no.

Alternativamente, un poco más corto,

find. -iname '*.zip' -exec sh -c '[ -e "${0%.zip}" ]' {} ';' -print

Esto también usa un script de shell de ayuda, pero solo está probando la existencia del nombre de archivo sin el sufijo .zip. Si existe un sufijo -menos nombre, se genera la ruta del archivo zip.

También posiblemente relevante:

1
15.06.2019, 03:11
3 ответа

Как намекает Подстановочный знак , скриптовый редактор упрощает эту задачу. Чтобы заменить строки с третьей по шестую после шаблона bb/bb/bb/bbодной строкой line uu/uu/uu/uu, вы можете использовать следующий конвейер ed:

printf '%s\n' '/bb\/bb\/bb\/bb' '+3,+6c' 'line uu/uu/uu/uu' '.' 'wq' | ed -s file.txt > /dev/null

На высоком уровне мы отправляем разделенные новой строкой -команды через конвейер в ed, из которых мы указываем молча редактировать файл с именем file.txtи перебрасывать любой «стандартный вывод» в долото -ковш /dev/null. Флаг -sподавляет нормальный вывод из edчисла прочитанных и записанных байтов. edтакже будет печатать совпадающие строки ("bb" в этом сценарии ), так что они отбрасываются через > /dev/null. Мы могли бы сбросить флаг -sи перенаправить как stdout, так и stderr.

Сами команды edявляются:

  • /bb\/bb\/bb\/bb--найдите строку, содержащую /bb/bb/bb/bb, где мы должны экранировать косую черту, потому что в противном случае edдумает, что мы пытаемся отправить странную bb/bb/bbкоманду на строку, соответствующую /bb/, из-за forard -косая черта — ситнатический символ.
  • +3,+6c--с этой строки, cвывесить строки с 3-й по 6-ю после нее...
  • line uu/uu/uu/uu--на эту строку
  • .--и скажите ed, что мы закончили замену строк
  • wq--затем wзаписать файл на диск и quited

Обратите внимание, что это предполагает наличие bb/bb/bb/bbв файле; в противном случае вы получите ошибку, когда попытаетесь указать edотредактировать строки с третьей по шестую после конца файла. Если вы не можете гарантировать, что шаблон существует в файле, вы можете поставить перед этим сценарием grep -q bb/bb/bb/bb file.txt && printf...для условного выполнения конвейера.

1
27.01.2020, 23:41

С ГНУsed:

sed -ne '\#bb/bb/bb/bb#{p;n;p;n;p;n;n;n;n;a line uu/uu/uu/uu' -e ';b };p' file.txt 

Выход:

line aa/aa/aa/aa
line bb/bb/bb/bb
line cc/cc/cc/cc
line dd/dd/dd/dd
line uu/uu/uu/uu
line ii/ii/ii/ii

Чтобы сохранить вывод в файл.txt , измените -neна -ine.


Обратите внимание, :пробел в коде с двумя переключателями -eсвязан с тем, что пробел указывает командеappend , где остановить добавление.

Другой метод заключается в использовании POSIX sed, но это не -однострочный вкладыш:

sed -n '\#bb/bb/bb/bb#{p;n;p;n;p;n;n;n;n;a\
line uu/uu/uu/uu
b };p' file.txt
0
27.01.2020, 23:41

В POSIX sedвы можете сделать следующее:

 $ sed -e '
   \:line bb/bb/bb/bb:!b
    n;n;n
    N;N;N
    s:.*:line uu/uu/uu/uu:
 ' inp

После того, как мы напечатали целевую строку и две строки после нее, мы накапливаем следующие три строки в пространстве шаблонов и заменяем все пространство шаблонов намеченной строкой. О переводе строки заботится сам sed при переносе пространства шаблона в стандартный вывод.

Обратите внимание, что мы предполагаем, что после целевой строки достаточно строк, чтобы Nне завершился ошибкой.

0
27.01.2020, 23:41

Теги

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