0

I need to use sh -c "command" where command is an awk with variables, but I haven't been able to, anyone can help?

Here is an example:

I have a file with several lines, and want to print the number of the lines that match a mark. In this case I use sh, but I will need to use ssh also.

$ file=file.txt
$ mark="xxxx"
$ cat $file
name
surname
xxxx
phone
xxxx
more data
more more data
xxxx
continue data
$ sh -c "awk -v line=\"$mark\" '$0 == line {print NR}' $file"
$ awk -v line="$mark" '$0 == line {print NR}' $file
3
5
8

The first run with sh returns nothing. The second run without sh runs ok.

==== more clarification

I have a function "execmd" that receives two parameters, first argument is a server name, the second is a string with a command

execmd ()
    {
    P_SERV="$1"
    P_CMD="$2"

    X_SERV=`hostname`
    if [ "$P_SERV" = "$X_SERV" ] ; then
   sh -c "$P_CMD"
    else
   ssh -n "$P_SERV" "$P_CMD"
    fi
    }

if i run:

xx=`execmd earth "awk -v line=\"$mark\" '\$0 == line {print NR}' $file"`; echo $xx

xx is empty

i put a echo inside execmd to see the command, and inside de function it translates the \$0 to bash is there any other thing i have to add? This is part of a mega script, where i have from one place monitor several ones, so if i have to run somthing locally i use sh, else ssh

Marcelo
  • 3
  • 2

1 Answers1

0

Enclose scripts with single quotes, not double, and then just open them up to expose shell variables if/when necessary in just that section of code:

$ sh -c 'awk -v line="'"$mark"'" '\''$0 == line {print NR}'\'' file'
3
5
8

To "include" single quotes in a single-quote delimited script is '\'', hence those strings around the awk script body instead of just ' alone.

Here's an example of why not to use double quotes like in the comments under your question, lets say you just want to print Eureka! every time you match a line:

$ sh -c 'awk -v line="'"$mark"'" '\''$0 == line {print NR, "Eureka!"}'\'' file'
3 Eureka!
5 Eureka!
8 Eureka!

compared to (and note we're already having to escape $0):

$ sh -c "awk -v line=$mark '\$0 == line {print NR, "Eureka!"}' file"
-bash: !"}': event not found

There's other things to consider too and it gets even worse if $mark contains globbing characters.

Ed Morton
  • 188,023
  • 17
  • 78
  • 185
  • 1
    Thanks @Ed Morton , could you please explain the difference between single quotes and double quotes? and in this case why do i have to put "'"$mark"'" instead of just "$mark" – Marcelo Apr 19 '18 at 18:19
  • A quick [google](https://stackoverflow.com/questions/6697753/difference-between-single-and-double-quotes-in-bash) produced https://stackoverflow.com/q/6697753/1745001 and more. The reason you need `line"'"$mark"'"` is that you WANT to end up with `line="xxxx"` and to get to that point you need to open up your `sh-c` command line with a `'` then provide the variable quoted to avoid the shell from expanding globbing chars, etc. so `"$mark"` and then re-start the sh-c part with `'`. Hope that makes sense. Just count the quotes and think about what exactly each is starting/stopping/enclosing. – Ed Morton Apr 19 '18 at 19:02