16

I have script that looks like this

#!/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.

What I want to do above is to print out in AWK the variable called 'basen' created before. But somehow it failed to do what I hoped it will.

So for example myfile.txt contain these lines

foo bar bax
foo qux bar

With the above bash script I hope to get

myfile bax
myfile bar

What's the right way to do it?

codeforester
  • 39,467
  • 16
  • 112
  • 140
neversaint
  • 60,904
  • 137
  • 310
  • 477
  • @tripleee How can this post be a duplicate? This is posted 7 years before and your suggested post 4 years ago. – neversaint Jun 07 '18 at 00:25
  • Yours is a common FAQ. Question age is not an important consideration when sorting duplicates. See also e.g. https://meta.stackoverflow.com/questions/252929/which-question-is-the-better-reference-for-a-duplicate/252930#252930 – tripleee Jun 07 '18 at 04:14

6 Answers6

29

The -v flag is for setting variables from the command line. Try something like this:

awk -v "BASEN=$basen" '{print BASEN "\t" $3}'
drawnonward
  • 53,459
  • 16
  • 107
  • 112
  • 2
    +1 This is the best way to inject a variable as it will work even if `$basen` contains special characters like apostrophes, quotes, or spaces. – John Kugelman Jun 23 '10 at 03:47
12

You can use it like this.

for i in `find $1 -name \*.jar`
do
jar tvf $i| awk -F '/' '/class/{print "'${i}'" " " $NF }' >> $classFile
done

You should use

"'${i}'"

in AWK to use the

$i

created in Bash Script.

syss
  • 232
  • 8
  • 18
iamxhu
  • 134
  • 5
  • 2
    use `$()` instead of backticks. And `find` with `for` loop like that will break on files with spaces. Quote your `$1` variable – ghostdog74 Jun 23 '10 at 05:44
4

Assuming you run awk as the sub process of the shell you declared the vars
Within the 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"];
}'

Result:

Reading values from within awk : whatever

notice the importance of export. With out it, the vars from the shell is considered local and does not get passed to the co-processes.

GreenFox
  • 1,112
  • 10
  • 5
4

you can just do everything in awk

awk '{gsub(".txt","",ARGV[1]);print ARGV[1] "\t" $3}' inputfile.txt
ghostdog74
  • 327,991
  • 56
  • 259
  • 343
2

The reason is that bash variables (environment variables) are not expanded within single-quoted strings. Try replacing

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

with

"{print \"$basen\" \"\t\" \$3}"
David Z
  • 128,184
  • 27
  • 255
  • 279
1

The easiest way is to make an awk variable. awk -v awkvar=$bashvar 'awkscript'.

Daenyth
  • 35,856
  • 13
  • 85
  • 124
  • you will need to put `awkvar=$bashvar` under doublequotes, otherwise it will have problems with bashvariables with spaces in it: `awk -v "awkvar=$bashvar" 'awkscript'` – syss Jun 28 '17 at 11:52