1

Я пытаюсь извлечь подстроку из строки с помощью sed на Cygwin.

#!/bin/bash

var1="foo\ bar"
var2="baz"

var3="$var1 $var2"

# extract "foo\ bar" from "foo\ bar baz"
var4=`echo $var3 | sed "s/"$var1"//"`
echo "$var4"

но я получаю следующий вывод, вызванный обратной косой чертой: sed: -e выражение # 1, char 6: неопределенная команда `s '

Как я могу написать команду sed для вывода 'Baz'?

3 ответа3

2

Проблема в том, что и shell, и sed интерпретируют обратную косую черту. Возможно, вам удастся заставить sed сделать это правильно, но я бы порекомендовал просто использовать другой инструмент, например, Perl:

#!/bin/bash
export var1="foo\ bar" ## The export allows Perl to access the variable as $ENV{var1}
var2="baz"
var3="$var1 $var2"

# extract "foo\ bar" from "foo\ bar baz"
var4=`echo $var3 | perl -ne '$var1=quotemeta($ENV{var1}); s/$var1//; print'`
echo "$var4"

В приведенном выше примере используется функция quotemeta Perl, которая экранирует все символы, не входящие в ASCII, позволяя регулярному выражению правильно соответствовать обратной косой черте.

Наконец, почему вы хотите это сделать? Вам действительно нужно сопоставлять \ или вы пытаетесь сопоставить пробелы в строках bash? Есть более простые способы, если это так.

1

проще говоря .... sed не работает .... как на колоннах, это более ориентированный на строки подход. Не заставляйте команду - используйте ее там, где это удобно. Вырезать будет лучше / проще

в качестве альтернативы, если вы ищете подстроку, то для этого также подойдет awk ... пример

Kaizen ~/so_test
$ echo "foo\ bar baz" | awk '{print substr($0,1,8)}'
+ echo 'foo\ bar baz'
+ awk '{print substr($0,1,8)}'
foo\ bar

в этом случае его проще использовать, достаточно ли этого?

0

Чтобы сделать это с помощью sed, нам нужно избежать обратной косой черты. Будьте готовы к безумию:

$ echo "$var1"
foo\ bar
$ echo "$var3"
foo\ bar baz
$ echo "$var3" | sed "s/$var1//"
foo\ bar baz
$ echo "${var1//\\/\\\\}"
foo\\ bar
$ echo "$var3" | sed "s/${var1//\\/\\\\}//"
 baz

Конечно, есть много других символов, которые также требуют экранирования, например * , поэтому perl-ответ @ terdon лучше, чем этот лес зубочисток.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .