Perl имеет специальный режим параграфов, в котором он определяет «строки» как параграфы. Это означает, что строка определяется двумя последовательными \ n
, а не одним. Из man perlrun
:
-0[octal/hexadecimal]
specifies the input record separator ($/) as an octal or
hexadecimal number. [. . .]
The special value 00 will cause Perl to slurp files in paragraph
mode.
Таким образом, вы можете написать сценарий perl, который печатает ваши переменные:
$ perl -00lne '/.*/; $v=$&; $v=~s/-/_/g; print "$v=\"$_\""' file
acpitz_virtual_0="acpitz-virtual-0
Adapter: Virtual device
temp1: +41.0°C (crit = +95.0°C)"
coretemp_isa_0000="coretemp-isa-0000
Adapter: ISA adapter
Core 0: +36.0°C (high = +90.0°C, crit = +90.0°C)
Core 1: +36.0°C (high = +90.0°C, crit = +90.0°C)"
А затем использовать eval
, чтобы указать вашей оболочке прочитать их:
$ eval "$(perl -00lne '/.*/; $v=$&; $v=~s/-/_/g; print "$v=\"$_\""' file )"
$ echo "$coretemp_isa_0000"
coretemp-isa-0000
Adapter: ISA adapter
Core 0: +36.0°C (high = +90.0°C, crit = +90.0°C)
Core 1: +36.0°C (high = +90.0°C, crit = +90.0°C)
Сценарий Perl может потребовать некоторых пояснений. Здесь то же самое, что и сценарий с комментариями:
## The . doesn't match newlines by default, so this is just a
## quick way of getting the text before the first \n, this will be
## you variable's name.
/.*/;
## $& is whatever was matched my the last match (//) operator. We set
## $v to that.
$v=$&;
## Bash doesn't like dashes in variable names, this will replace
## them with underscores.
$v=~s/-/_/g;
## Print the variable name and its value ($foo="bar")
print "$v=\"$_\""
Итак, я думаю, что здесь вас сбивает с толку формат команды, в котором первое слово (и )в команде являются назначением переменной (, которое оболочка определяет на основе наличия =
.)
В таких случаях оболочка оценит эти назначения, но только экспортирует эти переменные в выполняемой команде. В частности, сама оболочка не будет иметь доступа к этим переменным.
Это полезно для запуска команд или сценариев, на которые влияют переменные среды, и в этом случае вам не нужно экспортировать их в оболочку, и вы можете просто установить их как «один -offs» для этого единственного выполнения.
Давайте разберем ваши команды и объясним их одну за другой:
pwd echo 'aaa' # /home/me
Итак, это запуск команды pwd
и передача ей двух аргументов, echo
и aaa
. Но pwd
не принимает аргументов, поэтому он просто игнорирует эти два параметра и печатает локальный каталог.
val=pwd echo 'aaa' # aaa
Итак, как я объяснил, это выполняет присвоение переменной, устанавливая $val
для содержания строки pwd
, а затем выполняет команду echo
с аргументом aaa
. Переменная $val
доступна только для команды echo
, а не для самой оболочки! Команда echo
на самом деле ничего не делает с этой переменной, поэтому она просто выводит aaa
. После завершения этой команды переменная $val
становится , а не , определенной в оболочке.
val=pwd echo 'aaa'$val # aaa
Итак, снова аналогично команде выше. Это становится сложным, так как вы можете ожидать, что окончательный $val
будет расширен. Но переменные расширяются оболочкой , а не командами. И, как объяснено, оболочка на самом деле не видит $val
, для которого установлено значение pwd
, только команда (, в данном случае echo
), видит, поэтому $val
расширяется до пустой строки, и это точно эквивалентно вышеизложенному.
val=pwd echo 'aaa' && echo $val # aaa <and an empty line>
И еще раз,$val
недоступен после завершения первой команды echo
, поэтому вторая echo $val
ничего не напечатает (только пустую строку ), так как $val
никогда не устанавливался в самой оболочке на протяжении всего этого выполнения.
Если вы хотите установить $val
в оболочке, вам нужно сделать это назначение автономным, без каких-либо команд. Например, это ведет себя иначе, чем выше:
$ val=pwd; echo 'aaa' && echo $val
aaa
pwd
Поскольку за val=pwd
следует ;
, то оболочка считает это отдельной командой и установит $val
в текущей оболочке, поэтому echo $val
будет работать так, как вы ожидаете.
(Обратите внимание, что здесь есть еще одно отличие, так как с val=pwd;...
переменная $val
на самом деле не экспортируется, поэтому echo
не не увидит эту переменную в своем окружении, тогда как с val=pwd echo...
он будет экспортирован , но в этом случае он недоступен в оболочке.)
И, учитывая, что вы используете pwd
, интересно, вы хотели сохранить вывод этой команды в переменной... В этом случае вам нужно использовать подстановку команд оболочки , либо используя обратные кавычки, либо, что еще лучше, окружив команду $(
и )
.
Итак, последний пример здесь:
$ val=$(pwd); echo 'aaa' && echo $val
aaa
/home/me
Или:
$ val=$(pwd) && echo 'aaa' && echo $val
aaa
/home/me
(Здесь есть тонкая разница, где последний прервет выполнение, если команда внутри подстановки, в данном случае pwd
, завершится ошибкой и выйдет с ненулевым статусом -, и в этом случае следующие команды не будут выполняться. казнен. При использовании ;
это не так, следующие команды выполняются, даже если первая не удалась.)
Надеюсь, это объясняет, чего вы не понимали в этих командах!
приведенный ниже код может помочь понять, как работает эта конструкция:
$ cd tmprun/
$ cat run.sh
echo $a
$./run.sh
$ a=bla./run.sh
bla