У меня есть два набора командных строк:

make PREFIX=/usr                \
SHAREDIR=/usr/share/hwdata \
SHARED=yes
make PREFIX=/usr                \
SHAREDIR=/usr/share/hwdata \
SHARED=yes                 \
install install-lib

Я хочу вставить строку перед вторым make PREFIX=/usr.

Вот что я пробовал:

sed -e "/make PREFIX=\/usr/i\  sed -e '/\\\\\$(DIRINSTALL) -m 755 \\\\\$(DESTDIR)\\\\\$(SBINDIR)/ s/^/#/' \\\\\n\      -e '/\\\\\$(DIRINSTALL) -m 755 \\\\\$(DESTDIR)\\\\\$(LIBDIR)/ s/^/#/' \\\\\n\      -e 's/pci \\\\\$(DESTDIR)\\\\\$(PKGCFDIR)/pci/' \\\\\n\      -i Makefile" \
 >> $Output

$Output — имя файла сценария.

Он создает правильную команду sed (см. ниже) (некоторые \ были потеряны при отображении здесь), но, конечно, помещает строку над обоими шаблонами. Я пробовал различные уточнения вышеизложенного, но ничего не увенчалось успехом. Как вставить его выше только второго вхождения? Извините, но гугл меня не просветил. Я пишу это в сценарии Bash, поэтому мне было бы проще всего применить sed или awk. Я не знаю никакого Perl, поэтому предпочел бы не использовать его.

Вот строка, которую я хочу вставить. Вот как это должно выглядеть в сценарии Bash:

sed   -e '/\$(DIRINSTALL) -m 755 \$(DESTDIR)\$(SBINDIR)/ s/^/#/' \
      -e '/\$(DIRINSTALL) -m 755 \$(DESTDIR)\$(LIBDIR)/ s/^/#/' \
      -e 's/pci \$(DESTDIR)\$(PKGCFDIR)/pci/' \
      -i Makefile
0
fra-san 11 Окт 2020 в 14:48
1
Привет. Пожалуйста, опубликуйте желаемый пример вывода. Кроме того, я думаю, что " отсутствует в конце. Есть несколько способов выполнить вашу задачу. Если у вас есть только два набора, используйте tac, чтобы перевернуть строки, sed, чтобы вставить первый шаблон, затем снова tac. Лучший способ — добавить флаг в место удержания в первом шаблоне, чтобы во втором шаблоне вы поняли, что пора выполнить операцию вставки.
 – 
seshoumara
10 Окт 2020 в 22:56
Нам также нужно увидеть строку, которую вы хотите вставить. Ваша команда sed не завершена, так что это не помогает.
 – 
terdon
11 Окт 2020 в 01:59
Пожалуйста, отредактируйте свой вопрос и покажите нам, что вы ожидаете выход есть. Не помещайте его в комментарий, добавьте его к вопросу, где его легко увидеть.
 – 
terdon
11 Окт 2020 в 12:57
Обратите внимание, что вы можете отформатировать фрагменты как код, выбрав их в поле редактирования и нажав кнопку {} на панели над ним. Форматирование кода сохраняет любые символы (дословно), включая обратную косую черту.
 – 
fra-san
11 Окт 2020 в 14:27
Проверьте мое решение .. всего одна строка может исправить это
 – 
Sandeep Kothari
11 Окт 2020 в 14:38

4 ответа

Лучший ответ

Один из способов сделать это с помощью awk:

awk '
  index($0, "make PREFIX=/usr") && (++c == 2){
    print "sed -e \047/\\$(DIRINSTALL) -m 755 \\$(DESTDIR)\\$(SBINDIR)/ s/^/#/\047 \\"
    print "    -e \047/\\$(DIRINSTALL) -m 755 \\$(DESTDIR)\\$(LIBDIR)/ s/^/#/\047 \\"
    print "    -e \047/s/pci \\$(DESTDIR)\\$(PKGCFDIR)/pci/\047 \\"
    print "    -i Makefile"
  }
  1 # print current line
' file

Если в текущей строке присутствует строка make PREFIX=/usr (индекс > 0), предварительно инкрементируйте переменную c и сравните ее с 2. Если условие истинно, выведите строку для вставки. Затем распечатайте текущую строку. Одинарные кавычки записываются как восьмеричные \047.

0
Freddy 11 Окт 2020 в 13:50
Да, блестяще. Работает отлично. Огромное спасибо.
 – 
user1375531
11 Окт 2020 в 14:48

heredocs << — отличный и удобный способ избежать проблем с кавычками и обратной косой чертой в командной строке.

Мы передаем код в sed, который ищет первую команду make, а затем переходит к следующей. В этот момент вставка выполняется, и оттуда он скользит к eof, не беспокоясь ни о чем другом.

sed -f - file <<\eof 
  /make PREFIX=\/usr/!b
  :a;n;//!ba
  i\
sed -e '/\\$(DIRINSTALL) -m 755 \\$(DESTDIR)\\$(SBINDIR)/ s/^/#/' \\\
    -e '/\\$(DIRINSTALL) -m 755 \\$(DESTDIR)\\$(LIBDIR)/ s/^/#/' \\\
    -e 's/pci \\$(DESTDIR)\\$(PKGCFDIR)/pci/' \\\
-i Makefile
  :b;n;bb
eof

Это основано на ожидаемом результате.

1
Rakesh Sharma 11 Окт 2020 в 15:27

Я беру переменную "contentneed_to_replace" для замены контента перед строкой "сделать ПРЕФИКС"

for i in `sed -n '/make PREFIX/{;=;p}' o.txt| sed -n '1~2p'| sed -n '2p'`
do
contentneed_to_replace="praveen"
sed ''$i's/make PREFIX.*/'$contentneed_to_replace'\n&/g' o.txt
done

Выход

make PREFIX=/usr                \
 SHAREDIR=/usr/share/hwdata \
 SHARED=yes

 praveen
make PREFIX=/usr                \
 SHAREDIR=/usr/share/hwdata \
 SHARED=yes                 \
 install install-lib
0
Praveen Kumar BS 11 Окт 2020 в 11:05

Это должно работать... Он пропускает первое вхождение

sed -i -E '0,/make PREFIX/! s/(make PREFIX)/\n\1/' file.txt

File.txt

make PREFIX=/usr
SHAREDIR=/usr/share/hwdata
SHARED=yes
make PREFIX=/usr
SHAREDIR=/usr/share/hwdata
SHARED=yes
install install-lib
0
Sandeep Kothari 11 Окт 2020 в 14:36