У меня есть большое количество переменных bash в ch.sh

$ cat ch.sh
BBG=`tput setab 0`
RBG=`tput setab 1`
GBG=`tput setab 2`
.
.
.
$ cat abc
asd
bsd
csd
.
.
.

И я хочу получить доступ из awk без объявления awk -v для каждой переменной. Существует ли какой-либо метод? я пробовал это

source ch.sh
awk `
#Let s[asd]="B"
ta=s[$0] "BG" #s is awk array sowehow created by other file
#colour print of line in abc
` abc

Пожалуйста, предложите какой-нибудь метод.

0
Ed Morton 26 Сен 2020 в 15:09
3
Если они являются переменными среды (вы этого не говорите), они доступны как ENVIRON["varname"]. Кроме того, не могли бы вы опубликовать функциональный код? Код, который вы написали в вопросе, теперь содержит ошибки.
 – 
Kusalananda
26 Сен 2020 в 13:11
2
Если у вас есть большое количество переменных bash, к которым вы хотите получить доступ из awk, тогда ваш код awk тесно связан с вашим кодом bash, и поэтому, скорее всего, это будет плохое программное обеспечение. Возможно, вы захотите переосмыслить свой дизайн, чтобы лучше отделить то, что вы делаете в bash, от того, что вы делаете в awk.
 – 
Ed Morton
26 Сен 2020 в 13:19
1
Это мало что говорит нам, это, конечно, не объясняет, почему у вас есть файл с кучей переменных оболочки, к которым вам нужно получить доступ в awk-скрипте (если они нужны вам в оболочке, почему они вам также нужны в awk?Если они вам нужны в awk, почему они определены в сценарии оболочки?). Если вы можете показать минимальный пример кода bash+awk, который делает то, что вы пытаетесь сделать, вместе с кратким, тестируемым образцом входных данных и ожидаемым результатом, то мы можем лучше всего посоветовать вам, как это сделать правильно.
 – 
Ed Morton
26 Сен 2020 в 13:24
1
Вы все еще не показали маленькую программу bash+awk, которая демонстрирует, что вы пытаетесь сделать. Что делает содержимое ch.sh «переменными bash», а не просто парами tag="value", которые вы все равно могли бы прочитать из awk?
 – 
Ed Morton
26 Сен 2020 в 13:33
3
Я вижу, вы задали этот же вопрос на SO немного раньше, и он был закрыт там из-за неясности. Вы должны были принять этот отзыв и попытаться улучшить вопрос, прежде чем просто задать его снова, по сути, как есть на другом форуме.
 – 
Ed Morton
26 Сен 2020 в 14:30

3 ответа

Лучший ответ

Вы могли бы, если бы вам действительно пришлось (но, пожалуйста, прочитайте комментарий Эда ), напишите скрипт-обертку, который будет читать файл с переменными и добавлять их как -v options:

#/bin/bash

## The first argument is the file with the variables
varFile=$1
## Remove the first argument from the $@ array
shift;

## read the file and add the variables as -v declarations
while IFS="=" read -r var value; do
  varString=$varString" -v $var=${value} "
done < "$varFile"

## Run awk, with the -v declarations and whatever you
## gave on the command line.
awk $varString "$@"

Если вы сохраните этот скрипт как runAwk.sh в своем $PATH и сделаете его исполняемым (chmod a+x /home/auth/bin/runAwk.sh), вы сможете запустить:

runAwk.sh variables.txt 'awk command' data 

Например, учитывая эти два файла:

$ cat variables.txt 
var1=bob
var2=foo
var3=baz

$ cat data
1 2
3 4
5 6

Вы можете запустить:

$ foo.sh variables.txt '{print var1,var2,var3,$2;}' data 
bob foo baz 2
bob foo baz 4
bob foo baz 6

ВАЖНО: это не удастся, если в значениях переменных есть пробелы или другие пробелы. Например, он не может справиться с этим:

var1='something with spaces'

Если вам действительно нужно иметь дело с такими значениями, вам следует переосмыслить свой подход и не пытаться смешивать языки. Или, если вы не можете, используйте умный прием Эда Мортона и считывайте переменные в собственный массив awk .

1
terdon 26 Сен 2020 в 15:08
1
Было бы более надежно, если бы вы заполнили varArray вместо varString, и затем вы могли бы получить доступ к его содержимому как awk "${varArray[@]}" (т.е. в кавычках/защищено) вместо awk $varString ( подвержены/склонны к носовым демонам :-)). Предупреждение: я не проверял это утверждение!
 – 
Ed Morton
26 Сен 2020 в 13:57
2
Правда, но я выбрал простой путь и просто предложил ОП использовать ваш подход для более сложных значений. Это просто становится сложнее, чем оно того стоит, и было бы намного проще с другим подходом к одному языку.
 – 
terdon
26 Сен 2020 в 13:58

Похоже, вы просто думаете об этом неправильно, и все, что у вас есть на самом деле, это файл tag="value" пар в ch.sh, поэтому попробуйте следующее:

$ echo 7 |
awk '
    NR==FNR {
        tag = val = $0
        sub(/[[:space:]]*=.*/,"",tag)
        gsub(/^[^=]+=[[:space:]]*"?|"?[[:space:]]*$/,"",val)
        ch[tag] = val
        next
    }
    {
        tag = "var2"
        print ch[tag], $0
    }
' ch.sh -
zsd 7

И если это не все, что вам нужно, отредактируйте свой вопрос, чтобы предоставить минимальный пример кода bash + awk, демонстрирующий, что вы пытаетесь сделать.

2
Ed Morton 26 Сен 2020 в 14:02
Я отредактировал свой вопрос. Это вопрос домашнего задания. Поэтому я не могу дать полную информацию.
 – 
user429329
26 Сен 2020 в 15:26
Да, вы можете, просто создайте пример ввода, вывода и скрипт, демонстрирующий проблему. Возможно, вы захотите взглянуть на using-awk- to-color-the-output-in-bash/64046525#64046525
 – 
Ed Morton
27 Сен 2020 в 16:26

Предполагая, что ваш файл ch.sh содержит действительные назначения переменных оболочки, вы можете экспортировать эти переменные в среду, а затем ссылаться на них в своем сценарии AWK, используя ассоциативный массив ENVIRON.

Учитывая этот контент для abc:

asd
bsd
csd

И этот контент для ch.sh:

BBG=`tput setab 0`
RBG=`tput setab 1`
GBG=`tput setab 2`

чисто иллюстративный скрипт Bash может быть:

set -a
. ./ch.sh
set +a
awk '
  BEGIN {
    s["abc"] = "B"
    s["bsd"] = "G"
    s["csd"] = "R"
  }
  {
    ta = ENVIRON[s[$0] "BG"]
    printf("%s%s%s%s", ta, $0, ENVIRON["BBG"], ORS)
  }
' abc

set -a указывает оболочке пометить все вновь созданные или измененные переменные для экспорта (иначе они были бы недоступны для awk).

1
fra-san 26 Сен 2020 в 18:22