Интересно, что я столкнулся с тем, что у вас может быть группа захвата внутри группы, не участвующей в захвате. Посмотрите ниже регулярное выражение для соответствия веб-URL:
var parse_url_regex = /^(?:([A-Za-z]+):)(\/{0,3})([0-9.\-A-Za-z]+)(?::(\d+))?(?:\/([^?#]*))?(?:\?([^#]*))?(?:#(.*))?$/;
Введите строку url:
var url = "http://www.ora.com:80/goodparts?q#fragment";
Первая группа в моем регулярном выражении (?:([A-Za-z]+):)
- это не захватывающая группа который соответствует схеме протокола и символу двоеточия :
, т.е. http:
, но когда я работал под кодом, я видел, что первый индекс возвращаемого массива содержал строку http
, когда я думал, что http
и двоеточие :
оба не получат сообщения, поскольку они находятся внутри группы, не содержащей захвата.
console.debug(parse_url_regex.exec(url));
Я думал, что если первая группа (?:([A-Za-z]+):)
- это не захватывающая группа, то почему она возвращает строку http
в выходном массиве.
Итак, если вы заметили, что внутри группы, не содержащей захвата, есть вложенная группа ([A-Za-z]+)
. Эта вложенная группа ([A-Za-z]+)
является группой захвата (не имеющей ?:
в начале) сама по себе внутри группы, не захватывающей (?:([A-Za-z]+):)
. Вот почему текст http
по-прежнему захватывается, но символ двоеточия :
, который находится внутри группы не захвата, но вне группы захвата, не получает сообщения в выходном массиве.
Новые строки, которые вы ищете, есть, вы их просто не видите, потому что вы используете echo
без цитирования переменной.
Валидация :
$ a=$( df -H )
$ echo $a
Filesystem Size Used Avail Use% Mounted on /dev/sda3 276G 50G 213G 19% / udev 2.1G 4.1k 2.1G 1% /dev tmpfs 832M 820k 832M 1% /run none 5.3M 0 5.3M 0% /run/lock none 2.1G 320k 2.1G 1% /run/shm
$ echo "$a"
Filesystem Size Used Avail Use% Mounted on
/dev/sda3 276G 50G 213G 19% /
udev 2.1G 4.1k 2.1G 1% /dev
tmpfs 832M 820k 832M 1% /run
none 5.3M 0 5.3M 0% /run/lock
none 2.1G 320k 2.1G 1% /run/shm
$
Так как @ user4815162342 правильно указал , хотя новые строки в выходе не удаляются, trailing newlines удаляются с заменой команды. См. Эксперимент ниже:
$ a=$'test\n\n'
$ echo "$a"
test
$ b=$(echo "$a")
$ echo "$b"
test
$
В большинстве случаев это не имеет значения, потому что echo
добавит удаленную новую строку (если только она не вызывается с опцией -n
), но есть некоторые краевые случаи где в выводе программы есть еще одна конечная новая строка, и по какой-то причине они значительны.
В этом случае, как упоминалось в @Scrutinizer, вы можете использовать следующее обходное решение:
$ a=$(printf 'test\n\n'; printf x); a=${a%x}
$ echo "$a"
test
$
Объяснение: Символ x
равен добавляется к выходу (используя printf x
) после строк новой строки. Поскольку новые строки больше не trailing , они не удаляются подстановкой команд. Следующий шаг - удалить x
, который мы добавили, используя оператор %
в ${a%x}
. Теперь у нас есть исходный вывод со всеми новыми символами !!!
Вместо того, чтобы использовать подстановку команд для назначения вывода программы переменной, мы можем вместо этого использовать подстановку процесса для подачи вывода программы на read
встроенная команда (кредит для @ormaaj). Замена процесса сохраняет все новые строки. Чтение вывода в переменную несколько сложно, но вы можете сделать это следующим образом:
$ IFS= read -rd '' var < <( printf 'test\n\n' )
$ echo "$var"
test
$
Объяснение:
IFS=
. В противном случае read
не назначил весь вывод var
, а только первый токен. read
с параметрами -rd ''
. r
предназначен для того, чтобы предотвратить обратную косую черту в качестве специального символа, а с помощью d ''
установить разделитель на ничего, чтобы чтение читало весь вывод, а не только первую строку. Вместо того, чтобы использовать команду или замену процесса для назначения вывода программы переменной, мы можем вместо этого передать вывод программы команде read
(кредит @ormaaj). Трубопровод также сохраняет все новые строки. Обратите внимание, однако, что на этот раз мы установили необязательное поведение оболочки lastpipe
, используя встроенный shopt
. Это необходимо, так что команда read
выполняется в текущей среде оболочки. В противном случае переменная будет назначена в подоболочке, и она не будет доступна из остальной части скрипта.
$ cat test.sh
#!/bin/bash
shopt -s lastpipe
printf "test\n\n" | IFS= read -rd '' var
echo "$var"
$ ./test.sh
test
$
Я пытался обвести голову вокруг этого, потому что я использовал bash для потоковой передачи в результате запуска интерпретатора на скрипте F #. После некоторых проб и ошибок это оказалось для решения проблемы:
$ cat fsi.ch
#!/bin/bash
echo "$(fsharpi --quiet --exec --nologo $1)"
$ fsi.ch messages.fsx
Welcome to my program. Choose from the menu:
new | show | remove
Предполагая, что вам нужно запустить терминальную программу. Надеюсь, это поможет.