Всякий раз, когда вы хотите использовать переменные переменные, вероятно, лучше использовать словарь. Поэтому вместо записи
$foo = "bar"
$$foo = "baz"
вы пишете
mydict = {}
foo = "bar"
mydict[foo] = "baz"
Таким образом, вы не будете случайно перезаписывать ранее существовавшие переменные (что является аспектом безопасности), и вы можете иметь разные " Пространства имен». [/ д2]
# sed script to change "foo" to "bar" only on the first occurrence
1{x;s/^/first/;x;}
1,/foo/{x;/first/s///;x;s/foo/bar/;}
#---end of script---
или, если хотите: Примечание редактора: работает только с GNU sed
.
sed '0,/RE/s//to_that/' file
Следующая команда удаляет первое вхождение строки в файл. Он также удаляет пустую строку. Он представлен в XML-файле, но он будет работать с любым файлом.
Полезно, если вы работаете с файлами xml и хотите удалить тег. В этом примере он удаляет первое вхождение тега «isTag».
Команда:
sed -e 0,/'<isTag>false<\/isTag>'/{s/'<isTag>false<\/isTag>'//} -e 's/ *$//' -e '/^$/d' source.txt > output.txt
Исходный файл (source.txt)
<xml>
<testdata>
<canUseUpdate>true</canUseUpdate>
<isTag>false</isTag>
<moduleLocations>
<module>esa_jee6</module>
<isTag>false</isTag>
</moduleLocations>
<node>
<isTag>false</isTag>
</node>
</testdata>
</xml>
Результат файла (output.txt)
<xml>
<testdata>
<canUseUpdate>true</canUseUpdate>
<moduleLocations>
<module>esa_jee6</module>
<isTag>false</isTag>
</moduleLocations>
<node>
<isTag>false</isTag>
</node>
</testdata>
</xml>
ps: он не работал для меня в Solaris SunOS 5.10 (довольно старый), но он работает на Linux 2.6, sed версии 4.1.5
sed
(следовательно, он не работал с Solaris). Вы должны удалить это, пожалуйста - это действительно не дает отличительной новой информации на вопрос, которому было уже 4½ года, когда вы ответили. Конечно, у него есть пример работал, но это дискуссионный значение, когда вопрос имеет столько ответов, как это делает.
– Jonathan Leffler
17 January 2016 в 04:56
#!/bin/sed -f
1,/^#include/ {
/^#include/i\
#include "newfile.h"
}
Как работает этот скрипт: для строк между 1 и первым #include
(после строки 1), если строка начинается с #include
, затем добавьте указанную строку.
, если первая #include
находится в строке 1, то обе строки 1 и следующая последующая #include
будут иметь добавленную линию. Если вы используете GNU sed
, у него есть расширение, в котором 0,/^#include/
(вместо 1,
) поступит правильно.
Если кто-то пришел сюда, чтобы заменить символ для первого вхождения во всех строках (например, я), используйте это:
sed '/old/s/old/new/1' file
-bash-4.2$ cat file
123a456a789a
12a34a56
a12
-bash-4.2$ sed '/a/s/a/b/1' file
123b456a789a
12b34a56
b12
. Если вы, например, заменив 1 на 2, вы можете заменить все второе а вместо этого.
's/a/b/'
означает match a
и do just first match
for every matching line
– Samveen
6 October 2017 в 08:53
sed имеет очень простой синтаксис для этого: «-i» является интерактивным (нет необходимости в новом файле). Чтобы заменить только первый экземпляр:
sed -i 's/foo/bar/' file
, чтобы заменить глобально, вы использовали бы
sed -i 's/foo/bar/g' file
. В вашем примере я бы использовал (^ и $ - начало и конец строки соответственно )
sed -i 's/^#include/#include\n#include/' file
sed -i 's/foo/bar/' file
заменяет первый экземпляр foo на каждой строке; а не для всего файла.
– k107
7 June 2012 в 02:52
Я знаю, что это старый пост, но у меня было решение, которое я использовал:
grep -E -m 1 -n 'old' file | sed 's/:.*$//' - | sed 's/$/s\/old\/new\//' - | sed -f - file
В основном используйте grep, чтобы найти первое вхождение и остановиться там. Также напечатайте номер строки, т.е. 5: line. Труба, которая в sed и удалить: и что-нибудь после этого, вы просто остаетесь с номером строки. Труба, которая в sed, которая добавляет s /.*/ замену до конца, которая дает 1-строчный скрипт, который передается в последний sed для запуска в качестве скрипта в файле.
, так что если regex = #include и replace = blah, а первое обнаружение grep находит в строке 5, тогда данные, переданные в последний sed, будут 5s /.*/ blah /.
Возможное решение:
/#include/!{p;d;}
i\
#include "newfile.h"
:
n
b
Объяснение:
Использование FreeBSD ed
и избежать ошибки ed
«нет совпадения» в случае, если в обрабатываемом файле нет инструкции include
:
teststr='
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
'
# using FreeBSD ed
# to avoid ed's "no match" error, see
# *emphasized text*http://codesnippets.joyent.com/posts/show/11917
cat <<-'EOF' | sed -e 's/^ *//' -e 's/ *$//' | ed -s <(echo "$teststr")
H
,g/# *include/u\
u\
i\
#include "newfile.h"\
.
,p
q
EOF
Это может сработать для вас (GNU sed):
sed -si '/#include/{s//& "newfile.h\n&/;:a;$!{n;ba}}' file1 file2 file....
или если память не является проблемой:
sed -si ':a;$!{N;ba};s/#include/& "newfile.h\n&/' file1 file2 file...
Вы можете использовать awk для выполнения чего-то подобного.
awk '/#include/ && !done { print "#include \"newfile.h\""; done=1;}; 1;' file.c
Объяснение:
/#include/ && !done
Запускает оператор действия между {}, когда строка соответствует "#include" и мы еще не обработали его.
{print "#include \"newfile.h\""; done=1;}
Это печатает #include "newfile.h", нам нужно избежать кавычек. Затем мы устанавливаем переменную done в 1, поэтому мы не добавляем больше включений.
1;
Это означает «распечатать строку» - пустое действие по умолчанию для печати $ 0, которое выводит весь текст линия. Один лайнер и легче понять, чем sed IMO: -)
awk '/version/ && !done {print " \"version\": \"'${NEWVERSION}'\""; done=1;}; 1;' package.json
– Cereal Killer
7 August 2015 в 13:58
Я, наконец, получил это, чтобы работать в сценарии Bash, используемом для вставки уникальной метки времени в каждый элемент в фиде RSS:
sed "1,/====RSSpermalink====/s/====RSSpermalink====/${nowms}/" \
production-feed2.xml.tmp2 > production-feed2.xml.tmp.$counter
Он меняет только первое вхождение.
${nowms}
- это время в миллисекундах, установленное скриптом Perl, $counter
является счетчиком, используемым для управления контуром в скрипте, \
позволяет продолжить выполнение команды на следующей строке.
Файл читается, и stdout перенаправляется в рабочий файл.
Как я понимаю, 1,/====RSSpermalink====/
сообщает sed, когда останавливается, устанавливая ограничение диапазона, а затем s/====RSSpermalink====/${nowms}/
является знакомой командой sed, чтобы заменить первую строку на вторую.
В моем случае я помещаю эту команду в двойные кавычки, потому что я использую ее в скрипте Bash с переменными.
Достаточно полная коллекция ответов на linuxtopia sed FAQ . Также подчеркивается, что некоторые ответы, предоставленные людьми, не будут работать с версией sed, отличной от GNU, например
sed '0,/RE/s//to_that/' file
в версии, отличной от GNU, должно быть
sed -e '1s/RE/to_that/;t' -e '1,/RE/s//to_that/'
Однако эта версия не будет работать с gnu sed.
Вот версия, которая работает с обоими:
-e '/RE/{s//to_that/;:a' -e '$!N;$!ba' -e '}'
ex:
sed -e '/Apple/{s//Banana/;:a' -e '$!N;$!ba' -e '}' filename
sed: 1: "…": bad flag in substitute command: '}'
– ELLIOTTCABLE
7 January 2015 в 17:57
sed '1,/pattern/s/pattern/replacement/' filename
работает только в том случае, если «шаблон не будет отображаться в первой строке», на Mac. Я удалю свой предыдущий комментарий, поскольку он не является точным. Деталь можно найти здесь ( linuxtopia.org/online_books/linux_tool_guides/the_sed_faq/… ). Ответ Энди работает только для GNU sed, но не для Mac.
– Landys
11 April 2015 в 13:53
sed -e '1s/Apple/Banana/;t' -e '1,/Apple/s//Banana/'
. От ответа @ MikhailVS (в настоящее время) ниже.
– djb
28 April 2015 в 00:20
Ничего нового, но, возможно, немного более конкретного ответа: sed -rn '0,/foo(bar).*/ s%%\1%p'
Пример: xwininfo -name unity-launcher
производит вывод, например:
xwininfo: Window id: 0x2200003 "unity-launcher"
Absolute upper-left X: -2980
Absolute upper-left Y: -198
Relative upper-left X: 0
Relative upper-left Y: 0
Width: 2880
Height: 98
Depth: 24
Visual: 0x21
Visual Class: TrueColor
Border width: 0
Class: InputOutput
Colormap: 0x20 (installed)
Bit Gravity State: ForgetGravity
Window Gravity State: NorthWestGravity
Backing Store State: NotUseful
Save Under State: no
Map State: IsViewable
Override Redirect State: no
Corners: +-2980+-198 -2980+-198 -2980-1900 +-2980-1900
-geometry 2880x98+-2980+-198
Извлечение идентификатора окна с помощью xwininfo -name unity-launcher|sed -rn '0,/^xwininfo: Window id: (0x[0-9a-fA-F]+).*/ s%%\1%p'
:
0x2200003
В качестве альтернативного варианта вы можете посмотреть команду ed
.
man 1 ed
teststr='
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
'
# for in-place file editing use "ed -s file" and replace ",p" with "w"
# cf. http://wiki.bash-hackers.org/howto/edit-ed
cat <<-'EOF' | sed -e 's/^ *//' -e 's/ *$//' | ed -s <(echo "$teststr")
H
/# *include/i
#include "newfile.h"
.
,p
q
EOF
Просто добавьте число вхождений в конец:
sed s/#include/#include "newfile.h"\n#include/1
sed
указывает заменяющую команду с помощью: [2addr]s/BRE/replacement/flags
i> и отмечает, что «значение флагов должно быть равно нулю или больше: n i> Замените для n-го вхождения только BRE, найденного в пространстве шаблонов. Таким образом, по крайней мере, в POSIX 2008 трейлинг 1
не является расширением GNU sed
. Действительно, даже в стандарте SUS / POSIX 1997 это было поддержано, поэтому я был не в порядке в 2008 году.
– Jonathan Leffler
17 January 2016 в 04:44
Я бы сделал это с помощью awk-скрипта:
BEGIN {i=0}
(i==0) && /#include/ {print "#include \"newfile.h\""; i=1}
{print $0}
END {}
, затем запустил его с awk:
awk -f awkscript headerfile.h > headerfilenew.h
может быть неаккуратным, я новичок в этом.
0,
работает только сgnu sed
– Jotne 29 October 2014 в 09:59