grep на unix / linux: как заменить или перехватить текст? - PullRequest
5 голосов
/ 22 января 2011

Так что я довольно хорошо разбираюсь в регулярных выражениях, но у меня возникли некоторые проблемы с ними в unix.Вот две вещи, которые я хотел бы знать, как это сделать:

1) Заменить весь текст, кроме букв, цифр и подчеркивания

В PHP я бы сделалэто: (прекрасно работает)

preg_replace('#[^a-zA-Z0-9_]#','',$text).

В bash я пробовал это (с ограниченным успехом);похоже, что он не позволяет вам использовать полный набор регулярных выражений:

text="my #1 example!"
${text/[^a-zA-Z0-9_]/'')

Я пробовал его с помощью sed, но, похоже, все еще возникают проблемы с полным набором регулярных выражений:

echo "my #1 example!" | sed s/[^a-zA-Z0-9\_]//

Я уверен, что есть способ сделать это и с помощью grep, но он разбил его на несколько строк, когда я попытался:

echo abc\!\@\#\$\%\^\&\*\(222 | grep -Eos '[a-zA-Z0-9\_]+'

И, наконец, я также попытался использовать expr , но казалось, что действительно ограниченная поддержка расширенного регулярного выражения ...


2) Захват (несколько) частей текста

В PHP я мог бы просто сделать что-то вроде этого:

preg_match('#(word1).*(word2)#',$text,$matches);

Я не уверен, как это было бы возможно в * nix ...

Ответы [ 3 ]

14 голосов
/ 22 января 2011

Часть 1

Вы почти там с sed, просто добавьте модификатор g, чтобы замена произошла глобально, без g замена произойдет только один раз.

$ echo "my #1 example!" | sed s/[^a-zA-Z0-9\_]//g
my1example
$

Вы сделали ту же ошибку с заменой шаблона bash: глобальные замены не выполнялись:

$ text="my #1 example!"

# non-global replacement. Only the space is delete.
$ echo ${text/[^a-zA-Z0-9_]/''}
my#1 example!

# global replacement by adding an additional / 
$ echo ${text//[^a-zA-Z0-9_]/''}
my1example

Часть 2

Захват работает в sed так же, как и в регулярном выражении PHP: включение шаблона в круглые скобки приводит к захвату:

# swap foo and bar's number using capturing and back reference.
$ echo 'foo1 bar2' | sed -r 's/foo([0-9]+) bar([0-9]+)/foo\2 bar\1/'
foo2 bar1
$ 
1 голос
/ 22 января 2011

В качестве альтернативы хорошему ответу codaddict, используя sed, вы также можете использовать tr для первой части вашего вопроса.

echo "my #1 _ example!" | tr -d -C '[[:alnum:]_]'

Я также использовал класс символов [:alnum:], просто чтобы показать другой вариант.

0 голосов
/ 22 января 2011

что значит, что вы не можете использовать синтаксис регулярных выражений для bash?

$ text="my #1 example!"
$ echo ${text//[^a-zA-Z0-9_]/}
my1example

Вы должны использовать // для более чем 1 замены.

для вашего второго вопроса, с bash 3.2 ++

$ [[ $text =~ "(my).*(example)" ]]
$ echo ${BASH_REMATCH[1]}
my
$ echo ${BASH_REMATCH[2]}
example
...