Добавить одиночное -значение содержимого одного файла в качестве дополнительного столбца в другой файл

Переменные всегда доступны для подпроцессов -. В:

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 {...; }.

-2
15.09.2021, 09:09
5 ответов

Вы можете получить последнюю строку файла с помощью 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 ).

4
15.09.2021, 09:30

Поскольку это постоянная строка, которую вы туда добавляете, на ум приходит использование 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
2
15.09.2021, 09:32

Это будет работать независимо от того, какая строка находится в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
3
15.09.2021, 13:10

Использование 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» только в конец символа -, содержащего строку, измените (^.*$)на (^.+$).

Образец ввода:

  • файл1 :
    abc def
    ghi jkl
    
  • файл2 :
    hello
    

Пример вывода:

abc def hello
ghi jkl hello

Использование Raku для обработки ввода file1и file2(вместо прохождения через переменную оболочки)должно устранить ряд проблем, связанных с правильным экранированием ввода.

https://docs.raku.org/routine/subst
https://www.raku.org

0
15.09.2021, 22:19

Мы можем сделать так, как показано, и не беспокоиться об экранировании каких-либо символов:

$ sed rfile2 file1 | sed 'N;s/\n/ /'
abc def hello
ghi jkl hello
0
16.09.2021, 12:01

Теги

Похожие вопросы