Manipulate parameters in sh

I work with a utility ( unison , but that’s not the point) that takes parameters like:

$ unison -path path1 -path path2 -path path3 

I would like to write a sh script that I could run as follows:

 $ myscript path1 path2 path3 

I hope for a Posix compatible solution, but bash-specific will be good too.

I assume this should be something like:

 #!/bin/sh unison ${*/ / -path } 

But that will not work.

EDIT : Okay, I think I have something:

 #!/bin/bash PARAMS= for arg in " $@ " do PARAMS+=" -path '$arg'" done unison $PARAMS 

The problem is that this only works in bash, and I'm sure there is a better way to quote the parameters.

+4
source share
5 answers

Not selected, it can be simple:

 exec unison -path $1 -path $2 -path $3 

If you do not insert spaces in the names of your paths, you can deal with a variable number of arguments with:

 arglist="" for path in " $@ " do arglist="$arglist -path $path" done exec unison $arglist 

If you have spaces in the path names, you will have to work a lot harder; I usually use a user program called escape , which quotes arguments that require quotation marks, and eval :

 arglist="" for path in " $@ " do path=$(escape "$path") arglist="$arglist -path $path" done eval exec unison "$arglist" 

I note that using Perl or Python would make it easier to handle arguments with spaces in them, but the question asks about the shell.

In Bash, you can use a shell array variable - create arguments in the array and pass the array as arguments to the unison .

+5
source

If you use Bash arrays, all your quoting problems will go away.

 #!/bin/bash args=() for i in " $@ "; do # With Bash >= 3: args+=(-path "$i") # +=() doesn't work in Bash 2 # args=("${args[@]}" -path "$i") done exec unison "${args[@]}" 
+4
source

In Bash, you can use "${@/#/-path }" , which will replace the beginning of each positional parameter with "-path". To represent the end of a line, use % instead of # .

Here is a simple script demonstration using sed and the -e options again. (Of course, there are more efficient ways to use sed .)

 #!/bin/bash echo "Resulting arguments: ${@/#/-e }" sed "${@/#/-e }" 

And run it like this:

 $ echo abc | demo s/a/A/ s/b/B/ 

We get:

 Resulting arguments: -es/a/A/ -es/b/B/ ABc 
+3
source

If you want a strongly bash-specific version, you can try

  #!  / bin / sh

 eval eval exec \
   unison -path \\ \\\ "{$ (eval echo \\\" \\\ $ {1 .. $ #} \\\ "| sed 's / /, / g')} \\\"

If you delete all characters with a triple backslash, it will become easier to understand, but I will not ruin the fun by explaining this :-)

The main complication is to process file names with spaces. This explains the triple callback quote and double pricing.

+1
source

Here's how you can confidently quote your characters:

 job_strategy() { local p for p in " $@ "; do printf '-path\000%s\000' "$p" done } job_process() { xargs -0 unison } job_strategy "path1" "path2" "path3" | job_process 
+1
source

Source: https://habr.com/ru/post/1285909/


All Articles