Как я могу захватить текст между определенными разделителями в переменную оболочки? - PullRequest
6 голосов
/ 28 марта 2009

У меня небольшая проблема с указанием моей переменной. У меня есть файл с обычным текстом, и где-то в нем есть скобки [ ] (только 1 пара скобок во всем файле), и между ними есть текст. Мне нужно захватить текст в этих скобках в переменной оболочки (bash). Как я могу это сделать, пожалуйста?

Ответы [ 10 ]

9 голосов
/ 28 марта 2009

Bash / СЭД:

VARIABLE=$(tr -d '\n' filename | sed -n -e '/\[[^]]/s/^[^[]*\[\([^]]*\)].*$/\1/p')

Если это нечитаемо, вот несколько объяснений:

VARIABLE=`subexpression`      Assigns the variable VARIABLE to the output of the subexpression.

tr -d '\n' filename  Reads filename, deletes newline characters, and prints the result to sed's input

sed -n -e 'command'  Executes the sed command without printing any lines

/\[[^]]/             Execute the command only on lines which contain [some text]

s/                   Substitute
^[^[]*               Match any non-[ text
\[                   Match [
\([^]]*\)            Match any non-] text into group 1
]                    Match ]
.*$                  Match any text
/\1/                 Replaces the line with group 1
p                    Prints the line
6 голосов
/ 29 марта 2009

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

Оболочка предоставляет вам все необходимые инструменты:

$ var='foo[bar] pinch'
$ var=${var#*[}; var=${var%%]*}
$ echo "$var"
bar
3 голосов
/ 29 марта 2009

Сед не нужен:

var=`egrep -o '\[.*\]' FILENAME | tr -d ][`

Но это работает только с однострочными совпадениями.

2 голосов
/ 29 марта 2009

Использование встроенного сопоставления регулярных выражений Bash выглядит как еще один способ сделать это:

var='foo[bar] pinch'
[[ "$var" =~ [^\]\[]*\[([^\[]*)\].* ]]   # Bash 3.0
var="${BASH_REMATCH[1]}"
echo "$var"
1 голос
/ 28 марта 2009

Предполагается, что вы спрашиваете о переменной bash:

$ export YOUR_VAR=$(perl -ne'print $1 if /\[(.*?)\]/' your_file.txt)

Сказанное выше работает, если скобки находятся на одной строке.

1 голос
/ 28 марта 2009

А как же:

shell_variable=$(sed -ne '/\[/,/\]/{s/^.*\[//;s/\].*//;p;}' $file)

работал у меня на солярисе 10 под оболочкой корна; должен работать и с Bash. Замените '$(...)' обратными галочками в оболочке Bourne.

Редактировать : работает, когда задано [в одной строке и] в другой. Для случая с одной строкой используйте:

shell_variable=$(sed -n -e '/\[[^]]*$/,/\]/{s/^.*\[//;s/\].*//;p;}' \
                        -e '/\[.*\]/s/^.*\[\([^]]*\)\].*$/\1/p' $file)

Первый '-e' относится к многострочному спреду; второй '-e' относится к случаю с одной строкой. Первый '-e' говорит:

  • Из строки, содержащей открытую скобку [, за которой не следует закрывающая скобка ] в той же строке
  • До строки, содержащей закрывающую скобку ],
  • заменить все, вплоть до открытой скобки, пустой строкой,
  • заменить что-либо от закрывающей скобки и далее пустой строкой, а
  • распечатать результат

Второй '-e' говорит:

  • Для любой строки, содержащей как открытую, так и закрытую скобку
  • Замените шаблон, состоящий из «символов до и включая открытую скобку», «символов до, но исключая закрывающую скобку» (и помните об этом), «вещи из закрывающей скобки и далее» с запомненными символами в середине и
  • распечатать результат

Для многострочного корпуса:

$ file=xxx
$ cat xxx
sdsajdlajsdl
asdajsdkjsaldjsal
sdasdsad [aaaa
bbbbbbb
cccc] asdjsalkdjsaldjlsaj
asdjsalkdjlksjdlaj
asdasjdlkjsaldja
$ shell_variable=$(sed -n -e '/\[[^]]*$/,/\]/{s/^.*\[//;s/\].*//;p;}' \
                          -e '/\[.*\]/s/^.*\[\([^]]*\)\].*$/\1/p' $file)
$ echo $shell_variable
aaaa bbbbbbb cccc
$

А для однострочного корпуса:

$ cat xxx
sdsajdlajsdl
asdajsdkjsaldjsal
sdasdsad [aaaa bbbbbbb cccc] asdjsalkdjsaldjlsaj
asdjsalkdjlksjdlaj
asdasjdlkjsaldja
$
$ shell_variable=$(sed -n -e '/\[[^]]*$/,/\]/{s/^.*\[//;s/\].*//;p;}' \
                          -e '/\[.*\]/s/^.*\[\([^]]*\)\].*$/\1/p' $file)
$ echo $shell_variable
aaaa bbbbbbb cccc
$

Где-то здесь, становится все проще выполнять всю работу в Perl, отрывая файл и редактируя строку результата в двух многострочных операциях замены.

0 голосов
/ 01 апреля 2009

2 простых шага для извлечения текста.

  1. разделите переменную в [и получите правильную часть
  2. разделите переменную в] и получите левую часть
cb0$ var='foo[bar] pinch'
cb0$ var=${var#*[}
cb0$ var=${var%]*} && echo $var
bar
0 голосов
/ 29 марта 2009

Обратные слеши (BSL) были подобраны ...:

var='foo[bar] pinch' 
[[ "$var" =~ [^\]\[]*\[([^\[]*)\].* ]]   # Bash 3.0 
# Just in case ...: 
[[ "$var" =~ [^BSL]BSL[]*BSL[([^BSL[]*)BSL].* ]]   # Bash 3.0 
var="${BASH_REMATCH[1]}" 
echo "$var" 
0 голосов
/ 29 марта 2009

Спасибо всем, я использовал версию Strager и отлично работает, еще раз большое спасибо ...

var=`grep -e '\[.*\]' test.txt | sed -e 's/.*\[\(.*\)\].*/\1/' infile.txt`
0 голосов
/ 28 марта 2009
var=`grep -e '\[.*\]' test.txt | sed -e 's/.*\[\(.*\)\].*/\1/' infile.txt`
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...