Вставить строку в определенную позицию, если файл содержит определенную строку

Здесь две вещи. Сначала легкий:

«индивидуальный» — это просто другое слово для «личного», что означает (в данном случае )файл из домашнего каталога вашей учетной записи пользователя -. Обратите внимание на префикс ~/для всех личных/личных файлов.

В настольных системах, таких как ваш домашний компьютер, у вас обычно есть только одна учетная запись пользователя, но на компьютерах-серверах может быть зарегистрировано несколько учетных записей, и каждая из них имеет свой собственный домашний каталог и, следовательно, свой личный/индивидуальный .bash_profile, .bashrcи др.


Теперь самое сложное, и чтобы объяснить это, мне понадобится небольшое предисловие:

Bash проводит различие между «login » интерактивными -оболочками и «другими » интерактивными -оболочками. (У меня нет опыта работы с другими программами, такими как zshили ksh, но я полагаю, что они тоже ).

Например, в системах Linux оболочка входа в систему обычно является самой первой, которая запускается после того, как вы правильно (ввели )имя пользователя и пароль из текстовой консоли. или через сетевое соединение, такое как ssh.

Напротив, «другие » интерактивные -оболочки обычно запускаются графическим рабочим столом при щелчке по значку приложения эмулятора терминала.

« Другое » (т. е. не -вход в систему )интерактивные -оболочки также при последующем вызове вложенных интерактивных -оболочек даже из входа в систему один.

Практический пример этого последнего случая.Предположим, вы находитесь в приглашении первой оболочки после аутентификации себя (, т.е. вошли)на удаленный компьютер через ssh :, это логин интерактивная -оболочка; но если вы затем наберете bashи нажмете Enter, вы запустите новую другую интерактивную -оболочку. Вы можете вкладывать их столько, сколько хотите. Только, вам нужно набратьexit(или Control -D )для каждого из них, чтобы раскрутить запущенный вами стек вложенных интерактивных -оболочек.

В документации по Bash указано, какие файлы автоматически выполняются при запуске login оболочек и какие другие файлы при запуске других оболочек. Есть также пара файлов, которые автоматически запускаются только при выходе из входа в систему , но не при выходе из других оболочек.

1
22.05.2020, 09:47
1 ответ

Предполагая, что ваша команда,

sed -i '1 a #This is just a commented line'

работает для данного файла.

Чтобы применить это к некоторому файлу, somefile, если файл содержит строку <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-7">, вы можете использовать

if grep -q -F '<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-7">' somefile
then
    sed -i '1 a #This is just a commented line' somefile
fi

Параметр -qдля grepзаставляет утилиту останавливаться при первом совпадении и ничего не выводить (нас интересует только статус выхода ). Опция -Fзаставит grepрассматривать данный шаблон как строку, а не как регулярное выражение.

Чтобы применить это ко всем файлам в текущем каталоге (, пропуская файлы, которые не являются обычными файлами или символическими ссылками на обычные файлы):

pattern='<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-7">'

for name in./*; do
    [ ! -f "$name" ] && continue
    if grep -q -F -e "$pattern" "$name"; then
        sed -i '1 a #This is just a commented line' "$name"
    fi
done

Здесь я использую -e "$pattern"с опцией -e. Это хорошая привычка указывать шаблон для grepс помощью -e, когда шаблон хранится в переменной. Может возникнуть ситуация, когда значение переменной начинается с тире (не в этой конкретной задаче, очевидно, ), и это может сбить с толку grep, если -eне используется, заставляя его думать, что шаблон на самом деле является некоторым вариант командной строки.

Чтобы сделать это для всех файлов в текущем каталоге или ниже:

pattern='<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-7">'

find. -type f -exec sh -c '
    pattern=$1; shift
    for name do
        if grep -q -F -e "$pattern" "$name"; then
            sed -i "1 a #This is just a commented line" "$name"
        fi
    done' sh "$pattern" {} +

Выполняет короткий встроенный sh -cскрипт для пакетов найденных файлов, передавая шаблон в качестве первого аргумента командной строки скрипту и найденные пути в качестве остальных аргументов.

или, чтобы позволить findиспользовать grepв качестве теста, а затем выполнить sedдля файлов, прошедших тест,

pattern='<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-7">'

find. -type f \
    -exec grep -q -F -e "$pattern" {} \; \
    -exec sed -i '1 a #This is just a commented line' {} +

Используя {} +вместо {} \;в конце команды sedвыше, мы даем sedкак можно больше входных файлов одновременно, а не выполняем sedпо одному разу для каждого файла. Это требует, чтобы GNU sedработал правильно, но поскольку вы уже используете синтаксис GNU sedв своей команде a, я предполагаю, что это нормально.

См. также Описание опции -exec команды `find`

2
18.03.2021, 23:33

Теги

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