Переменные всегда доступны для подпроцессов -. В:
a=1
(echo "$a")
вы видите 1.
Я думаю, вы имели в виду, что вы хотите, чтобы переменная имела локальную область действия и экспортировалась в среду, чтобы они передавались как переменные среды командам, которые выполняются .Выполнение команды — это то, что стирает память процесса (, а среда — это способ сохранить некоторые данные в нем ), разветвление дочернего процесса копирует всю память, поэтому все сохраняется.
Для этого вы можете использоватьlocal -x
:
a=(1 2)
f() {
local -x a=3
typeset -p a
printenv a # printenv being *executed*
}
f
typeset -p a
дает:
typeset -x a=3
3
typeset -a a=( 1 2 )
Или вы можете export
после объявленияlocal
:
a=(1 2)
f() {
local a=3
export a
typeset -p a
printenv a # printenv being *executed*
}
f
typeset -p a
Обратите внимание, что вы можете передать переменную в среде одной команды, не определяя ее иначе как переменную оболочки с помощью:
a=(1 2)
f() {
a=3 printenv a # printenv being *executed*
}
f
typeset -p a
Обратите внимание, что local
появился в оболочке Almquist в конце 80-х, но работает иначе, чем zsh
. В оболочке Almquist (и ее потомках, таких как dash и sh в NetBSD/FreeBSD ), local
влияет только на область действия переменной и не изменяет значение или атрибуты переменной.
zsh local
работает больше как ksh93 typeset
в том смысле, что объявляет совершенно новую переменную, независимую от переменной во внешней области видимости.
ksh88, bash и pdksh local
/ typeset
также пытаются сделать это, но все еще наследуют некоторые атрибуты от переменной внешней области, включая атрибут export . Это изменилось в ksh93, хотя обратите внимание, что ksh93 также переключился на статическую область видимости и реализует локальную область видимости только в функциях, объявленных с синтаксисом function f {...; }
.
Вы можете получить последнюю строку файла с помощью tail
, а затем передать ее как внешнюю переменную в awk
, указав awk
напечатать каждую строку и переменную:
$ awk -v s="$(tail -n1 file2)" '{print $0,s}' file1
abc def hello
ghi jkl hello
Обратите внимание, что это предполагает, что i )вам нужна последняя строка file2
; если это не так, вы можете заменить tail -n1 file
на cat "$file"
и ii ), что file2
не содержит управляющих последовательностей (см. Как использовать переменные оболочки в сценарии awk? на SO ).
Поскольку это постоянная строка, которую вы туда добавляете, на ум приходит использование sed с оговоркой, что добавляемая строка встроена в командную строку sed, поэтому все, что обработано sed специально, не будет восприниматься как -. Например. /
будет использоваться для завершения команды s///
, а &
будет заменен частью шаблона.
$ str=$(cat file2)
$ sed -e "s/\$/ $str/" file1
abc def hello
ghi jkl hello
См., например,. обсуждение в:Замена первого вхождения шаблона в файле, который может содержать косую черту
То же самое и с awk, хотя он также не настолько -независим от содержимого, как можно было бы подумать, поскольку для строк, заданных с помощью -v
, awk обрабатывает обратную косую черту в стиле C -, так что строка foo\tbar
будет превратитесь в foo[tab]bar
, что может быть, а может и не быть тем, что вы хотите.
$ str=$(cat file2)
$ awk -v str="$str" '{print $0 " " str}' < file1
abc def hello
ghi jkl hello
См., например,.:Использовать переменную оболочки в awk
Или, я думаю, вы могли бы использовать и другие инструменты, хотя это получилось немного в стиле Руба Голдберга -. Я не знаю, что привело меня к этому:
$ paste file1 <( yes "$(cat file2)" ) | head -n "$(wc -l < file1)"
abc def hello
ghi jkl hello
Это будет работать независимо от того, какая строка находится вfile2
:
$ awk 'NR==FNR{x=$0; next} {print $0, x}' file2 file1
abc def hello
ghi jkl hello
или, если хотите, и если строка в файле2 не может содержать обратную косую черту,(-v
интерпретирует escape-последовательности):
$ awk -v x="$(< file2)" '{print $0, x}' file1
abc def hello
ghi jkl hello
Вот разница:
$ cat file2
hello\there
$ awk 'NR==FNR{x=$0; next} {print $0, x}' file2 file1
abc def hello\there
ghi jkl hello\there
$ awk -v x=$(< file2) '{print $0, x}' file1
abc def hello here
ghi jkl hello here
Использование Raku (, ранее известного как Perl _6)
raku -e 'my $str="/path/to/file2".IO.lines(1);.subst(/(^.*$)/, {$0,$str}).put for lines;' file1
Вкратце, первая (и предположительно единственная )строка file2
считывается в переменную $str
, затем file1
анализируется построчно,subst
-ituting (действительно, добавление)$str
до конца каждой строки, даже пустых строк. Чтобы изменить поведение на добавление «hello» только в конец символа -, содержащего строку, измените (^.*$)
на (^.+$)
.
Образец ввода:
abc def
ghi jkl
hello
Пример вывода:
abc def hello
ghi jkl hello
Использование Raku для обработки ввода file1
и file2
(вместо прохождения через переменную оболочки)должно устранить ряд проблем, связанных с правильным экранированием ввода.
Мы можем сделать так, как показано, и не беспокоиться об экранировании каких-либо символов:
$ sed rfile2 file1 | sed 'N;s/\n/ /'
abc def hello
ghi jkl hello