如何让AWK使用在Bash脚本中创建的变量

16
我有一个看起来像这样的脚本
#!/bin/bash
#exampel inputfile is "myfile.txt"
inputfile=$1
basen=`basename $inputfile .txt`  # create basename

cat $inputfile | 
awk '{print $basen "\t" $3}  # this doesn't print "myfile" but the whole content of it.

我想要做的是在AWK中打印出之前创建的名为'basen'的变量。 但不知何故它未能实现我所希望的。

所以例如 myfile.txt 包含这些行

foo bar bax
foo qux bar

通过上述的bash脚本,我希望能够得到以下结果。
myfile bax
myfile bar

什么是正确的做法?

@tripleee 这篇文章怎么可能是重复的?这篇文章发布于7年前,而你建议的文章则是4年前。 - neversaint
你的问题是一个常见的FAQ。在排序重复内容时,问题的提出时间并不是一个重要的考虑因素。另请参阅例如https://meta.stackoverflow.com/questions/252929/which-question-is-the-better-reference-for-a-duplicate/252930#252930。 - tripleee
6个回答

29
< p > -v 标志用于从命令行设置变量。尝试像这样做:

awk -v "BASEN=$basen" '{print BASEN "\t" $3}'

2
+1 这是最佳的注入变量方式,即使 $basen 包含特殊字符如撇号、引号或空格也能正常工作。 - John Kugelman

12
你可以像这样使用它。
for i in `find $1 -name \*.jar`
do
jar tvf $i| awk -F '/' '/class/{print "'${i}'" " " $NF }' >> $classFile
done

在AWK中应该使用

"'${i}'"

来使用Bash脚本中创建的

$i


2
使用$()代替反引号。而且像那样使用findfor循环会在文件名中含有空格时出错。请引用您的$1变量。 - ghostdog74

4
您可以在awk中完成所有操作。
awk '{gsub(".txt","",ARGV[1]);print ARGV[1] "\t" $3}' inputfile.txt

4

假设你在shell的子进程中运行awk,并声明了变量
在shell中

export MY_VARS="whatever"; #// IT NEEDS to be exported, to allow the sub process awk read access.
echo ""| awk '{
    print "Reading values from within awk : "ENVIRON["MY_VARS"];
}'

结果:

在awk中读取数值:任何。

请注意export的重要性。如果没有它,来自shell的变量被视为本地变量,不会传递给子进程。


2

原因是bash变量(环境变量)在单引号字符串中不会被扩展。尝试替换

'{print $basen "\t" $3}'

使用

"{print \"$basen\" \"\t\" \$3}"

那里有一个宝石 :) 谢谢DavidZ! - Deian

1
最简单的方法是创建一个 awk 变量。 awk -v awkvar=$bashvar 'awkscript'

你需要在双引号中将awkvar=$bashvar引起来,否则可能会遇到包含空格的bash变量问题:awk -v "awkvar=$bashvar" 'awkscript' - syss

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接