Согласно комментарию Стефана Чазеласа , проблема не в том, что пробел интерпретируется как новая строка. Он объяснил это в другом месте в связи с (концептуальным) оператором «split + glob», и хотя я не полностью следую его семантике, вот что происходит:
Переменная без кавычек разделяется на пробеле оболочкой, и они передаются в качестве аргументов в echo
. Разделение удаляет пробелы.Это может немного сбивать с толку, так как «обратная косая черта-новая строка» кажется escape-последовательностью, но это НЕ эквивалентно x = \\\ n
, это эквивалентно x = $ '\\ \ 012 '
, \ 012
является восьмеричным для фактического перевода строки - в отличие от escape-последовательности \\ n
, которая приводит к строке, содержащей литерал "\ n "(обратная косая черта-n), которая не будет разделена.
echo
затем выводит свои аргументы, разделенные пробелом.
Повторим:
str1=hello\\nworld
str2=$'hello\012world'
Оболочка не будет разделять первую оболочку без кавычек, поскольку она фактически не содержит пробелов - она содержит escape-последовательность \ n
, тогда как во втором случае она будет быть разделенным без кавычек на фактическом символе новой строки (который является пробелом).
Поскольку qemu — это долго работающая программа, и она не возвращается к подсказке, проще открыть другой терминал и проверить, :какой IP-ПОРТ использует qemu. Итак, команда
$ netstat -tulpn | grep qemu-system | awk '{print $4}'
127.0.0.1:5900
Спасибо за предложения.
Я бы использовал tail
и sed
или простоsed
напр.
address=$(the_above_command | sed -r -e 's/VNC server running on ([0-9.:]+)$/\1/')
echo "$address" #or some other command
Проверьте бит в ()
, чтобы убедиться, что он дает то, что вы хотите. $(cmd)
является подстановкой, она берет стандартный вывод cmd
и заменяет себя этим выводом. Затем строка повторно -анализируется.
Примечание. :Если программа запущена/продолжает выполняться, вы не можете знать, является ли текущая строка последней строкой. К счастью, я не думаю, что вам нужно знать, что это последняя строка.
Здесь было бы полезно использовать комбинацию grep
и cut
.
Вы можете извлечь последнюю строку с помощью
grep -m1 'VNC server running on'
Флаг -m1
будет означать, что grep прекратит чтение после первого совпадения, так как это предположительно длительный процесс.
Затем вы можете вырезать адрес с помощью
cut -d' ' -f5
Если вы хотите направить вывод в другой процесс, вы, вероятно, захотите запустить qemu
в фоновом режиме следующим образом:
(qemu-system-x86_64... &) | grep -m1 'VNC server running on' | cut -d' ' -f5
Это должно работать:
grep -m1 -oP '(\d{1,3}\.?){4}:\d{1,5}' <( your-qemu-command 2>&1 )
<( your-qemu-command 2>&1 )
— это замена процесса, которая запускает qemu
с перенаправлением stdout/stderr в анонимный канал или FIFO; grep
читает из канала/FIFO, грубо ища шаблон IP :PORT, где IP относится к IPv4-адресу.Параметр -o
для grep
гарантирует, что будет напечатана только комбинация IP :PORT совпадающей строки; опция -m1
гарантирует, что grep
вернется к подсказке после того, как найдет то, что искал (, т. е. выйдет при первом совпадении ). Параметр -P
указывает на использование синтаксиса регулярных выражений Perl. qemu
продолжает работать в фоновом режиме, пока не завершится. Любой вывод на stdout/stderr с помощью qemu
после завершения команды grep
теряется, но, поскольку предполагается, что комбинация IP :PORT является последним выводом, это не должно вызывать беспокойства. Если вы хотите захватить вывод вышеуказанной команды, просто оберните его подстановкой команды $(...)
вот так:
ip_port=$( grep...etc )