Is there a common expectation how something_else should behave?
Да, как обычная команда. Оболочка не понимает command1 command2
как две команды, это одна команда и один аргумент (, даже если это может быть имя действительного двоичного файла, найденного в /bin
, например ). Это command1
, который позже запускает command2
через системный вызов exec()
, а не через оболочку.
Are there shell constructs that can disambiguate these commands (like which program's output is redirected)
Нет, someting_else
не будет рассматриваться как-то особенно. Как сказано выше, нет другой конструкции, кроме одной команды и одного аргумента. Также кажется, что путаница в этом вопросе заключается в том, что и strace
, и foo
предполагаются запущенными оболочкой, но на самом деле это цепочка родительских -дочерних процессов.
Bourne -как и оболочки (это bash
, dash
,ksh
)все следуют правилам POSIX в отношении того, как интерпретируются команды. POSIX определяет:«Простая команда» — это последовательность необязательных присвоений переменных и перенаправлений в любой последовательности, за которыми могут следовать слова и перенаправления, завершающиеся управляющим оператором». Это можно представить в виде:
[VAR=foo BAR=baz] command1 [arg1, arg2...] [ n>m ]
Общее правило заключается в том, что перенаправление применяется к команде, которая будет оставлена большинством не -слова назначения. В вашем примере strace
— это команда, а foo
— аргумент для strace
. Перенаправления применяются только к команде, а не к аргументам, то есть к strace
. foo
запускается не оболочкой, а strace
, и в этом случае foo
становится дочерним процессом strace
. Точно так же somethingelse
будет рассматриваться как команда с foo
в качестве аргумента.
Что касается не встроенных -команд, они являются дочерними процессами оболочки, а дочерние процессы наследуют файловые дескрипторы оболочки, поэтому они обычно не управляют перенаправлениями -, они получают «предварительно упакованные» места назначения., так что, что касается strace
и 2>/dev/null
,ему, вероятно, все равно, какой на самом деле файловый дескриптор 2 (, если он не активно проверяет уровень исходного кода ). strace
по-прежнему будет записывать вывод в файловый дескриптор 2, но оболочка уже подключила -этот файловый дескриптор, чтобы он указывал на /dev/null
.
Поскольку файловые дескрипторы наследуются, это также объясняет, почему, если вы делаете что-то вроде strace stat noexist 2>stracelog.txt
, оба потока ошибок из strace
и stat
попадают в один и тот же файл. Напротив, некоторые команды позволяют явно указать пункт назначения в качестве одной из своих опций. Таким образом, с strace -o tracelog.txt stat noexist 2>stracelog.txt
у вас есть вывод только из stat
в файл stracelog.txt
-, хотя дескриптор файла унаследован, теперь флаг -o
является свойством strace
, а вывод управляется командой даже если дескриптор файла унаследован.
Это также дает нам небольшой намек :на то, что теоретически команды могут «перенаправлять» в смысле дублирования файловых дескрипторов на существующие с помощью dup2()
системного вызова, который является точно таким же механизмом, который использовали бы оболочки, но насколько >
тип символов перенаправления -, который все еще находится под контролем оболочки и, следовательно, интерпретируется только родительской оболочкой.
Общепринято, что диагностический вывод направляется на stderr
. На самом деле у нас уже есть два отличных поста на эту тему:
Находятся ли отчеты о ходе работы/информация журнала в stderr или stdout?
Когда использовать стандартный поток ошибок в приложении командной строки -?
watch
и strace
в ваших примерах следуют соглашению, вот и все. Нет необходимости указывать 2>/dev/null
для скрытия вывода таких команд как такового.
Если вы хотите указать перенаправления для команды, которую вы передаете в качестве аргумента, например, на strace
, вам понадобится оболочка вокруг нее. Например,
strace -f bash -c 'stat /etc/passwd nonexisting 2>/dev/null'
Обратите внимание на использование флага -f
, так как если вы сосредоточены на отслеживании системных вызовов применительно к команде stat
,вы можете не увидеть их без флага -f
.
Поскольку вы используете bash
, нет необходимости использовать ни awk
, ни sed
string='XXXX · YYYY· ZZZZ'
printf '%s\n' "${string:7:4}"
YYYY
Строка не очень удобна для обработки с помощью sed
. Если мы предположим, что у вас есть ·
в качестве префикса и ·
в качестве суффикса, вы можете выбрать это следующим образом
string='XXXX · YYYY· ZZZZ'
printf '%s\n' "$string" | sed -nE 's/^.*· ([^· ]+)·.*/\1/p'
YYYY
Однако ERE неудобен
^ # Bind to start-of-line
.* # Any character, zero or more times
· # Literal dot and space
( # Start of a bracketed group
[^· ]+ # NOT dot or space, at least once
)
· # Literal dot
.* # Any character, zero or more times
\1 # The value of the first bracketed expression
Вероятно, стоит отметить, что символ точки, используемый в этом выражении, не является десятичной точкой/точкой на стандартной клавиатуре; это средняя точка , представленная в UTF -8 как 0xc2 0xb7.