BorisRu
BorisRu

Reputation: 227

Finding the exact shell variable with grep/awk/sed

I'm trying to find an exact match of a certain string that contains backslashes and spaces, but I can't seem to get the correct technique that only returns one match (see example). The problem occurs where there are more 'versions' of the same variable, as shown below.

Two examples of variables would be:
variable_i_want="Database\Base\location of site"
variable_dont_want="Database\Base\location of site - remote"

The file i'm searching in is structured as follows (all columns are tab seperated):

Database\Base\location of site             data1    data2    data3   
Database\Base\location of site - remote    data1    data2    data3  
Other_variable\something                   data1    data2    data3

My goal would be to only match the first line in this case.
Things i've tried so far:

awk -v pattern="$variable_i_want" -F\\t '$1~pattern {print $1,$2,$3}' file.txt
returns
awk: warning: escape sequence '\B' treated as plain 'B'

grep -F "$variable_i_want" file.txt
returns lines containing both matches (location of site and location of site - remote). Leaving out the -F returns nothing because it interprets the backslashes and spaces as code instead of string (i guess)

I think a possible solution would be to match the variable in combination with a regex, something like ^$variable_i_want$ but I can't get this to work in either sed/awk or grep.

So, for clarity: i only want the line containing $variable_i_want to match.

Upvotes: 4

Views: 88

Answers (3)

RavinderSingh13
RavinderSingh13

Reputation: 133780

After chatting with OP got to know his/her O.S is Ubnutu, so written and tested this code with Ubuntu 16.04.6

variable_dont_want='Database\\Base\\location of site - remote'
variable_i_want='Database\\Base\\location of site'

Now run following code:

awk -v var="$variable_i_want" -v var1="$variable_dont_want" 'index($0,var) && !index($0,var1)' Input_file

Output of above code was as follows.

Database\Base\location of site             data1    data2    data3

So we need to do 2 things here to make this work with awk:

  • Have bash variables single quoted wrapped, rather than " to take \ as a literal character, we need to tell variable that we need 2 of \ in it.
  • Now why we need to make variable understand that read \ as \\ because of awk it should be escaped so that awk will NOT give warning messages etc.

Upvotes: 2

HardcoreHenry
HardcoreHenry

Reputation: 6387

If you have bash 4.4 or up, you can do

grep "^${variable_i_want@Q}$"$'\t' file.txt

The ^ matches the begining of the line, the $'\t' matches a tab character (note, this has to be outside of the original quotes...). the ${...@Q} escapes the backslashes and spaces in a manner that grep accepts. If you have an older version of bash, you can use the printf %q instead:

grep "^$(printf %q "$variable_i_want")"$'\t' file.txt

or

grep "^$(printf "%q\t" "$variable_i_want")" file.txt

(since you're using printf anyways, you can have it output a literal tab character...)

example:

tmp> more file.txt
blah
Database\Base\location of site  data1   data2   data3
Database\Base\location of site - remote data1   data2   data3

tmp> printf "%q\n" "$variable_i_want"
Database\\Base\\location\ of\ site

tmp> grep "^$(printf "%q" "$variable_i_want")"$'\t' file.txt
Database\Base\location of site  data1   data2   data3

Upvotes: 1

Daemon Painter
Daemon Painter

Reputation: 3520

You might want to escape \B and use the $ to enforce it to be at the end of the hook.

awk -F\\t '$1~/Database\\Base\\location of site$/ {print $1,$2,$3}' file.txt

Upvotes: 0

Related Questions