Linux/Bash: How to unquote?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6988288/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 00:32:52  来源:igfitidea点击:

Linux/Bash: How to unquote?

linuxbashshellcommand-linearguments

提问by Daniel Marschall

Following command

Following command

echo 'a b' 'c'

outputs

outputs

a b c

But the following

But the following

X="'a b' 'c'"
echo $X;

will outout

will outout

'a b' 'c'

I am searching a way to unquote $X , so that it will output "a b c" , but without losing the merged 'a b' argument. (= 2 arguments instead of 3, makes no difference for command 'echo', but for other commands like 'cp')

I am searching a way to unquote $X , so that it will output "a b c" , but without losing the merged 'a b' argument. (= 2 arguments instead of 3, makes no difference for command 'echo', but for other commands like 'cp')

采纳答案by vanza

Try xargs:

Try xargs:

$ echo $x
'a b' 'c'

$ echo $x | xargs ./echo
argc = 3
argv[0] = ./echo
argv[1] = a b
argv[2] = c

回答by Karoly Horvath

eval echo $x

this will pass a bas first argument and cas the second one

this will pass a bas first argument and cas the second one

Note: this will actually evaluate arguments, eg:

Note: this will actually evaluate arguments, eg:

$ x='$((3+5))'
$ eval echo $x
8

If that's not what you want use @vanza's xargs.

If that's not what you want use @vanza's xargs.

回答by Gordon Davisson

Usually, if you're trying to store multiple "words" in a single variable, the recommended method isn't to use embedded quotes, but to use an array:

Usually, if you're trying to store multiple "words" in a single variable, the recommended method isn't to use embedded quotes, but to use an array:

X=('a b' 'c')
printf "%s\n" "${X[@]}"

prints:

prints:

a b
c

回答by larzq

It is also possible to combine xargsand sh -c 'cmd' _ arg1 arg2 ...to reparse arguments into the positional parameter array $@.

It is also possible to combine xargsand sh -c 'cmd' _ arg1 arg2 ...to reparse arguments into the positional parameter array $@.

Assigning the output to a variable and redirecting anything but the exit status $?of the last process to stderr, for example, makes it possible to store the exit code of the last process in a variable and use it after xargshas ended execution.

Assigning the output to a variable and redirecting anything but the exit status $?of the last process to stderr, for example, makes it possible to store the exit code of the last process in a variable and use it after xargshas ended execution.

X="'a b' 'c'"

ret="$(
export IFS=''
set -o pipefail
echo $X | xargs sh -c '
   for file in "$@"; do
      echo cp "$file" destdir 1>&2 || { echo $?; kill -HUP $PPID; exit $?; } 
      #(exit 3) || { echo $?; kill -HUP $PPID; exit $?; }
      #(exit 3) || { echo $?; kill -HUP $PPID; kill -HUP -- -$$; }
  done
  echo $?
' _
echo $? '|' ${PIPESTATUS[@]} 1>&2
)"
echo "$ret" | tail -1

回答by user.friendly

Please don't use eval for something like this. setwill keep the integrity of the parameters and commands other than echowill play nicely with them. Just keep in mind you'll lose the reference(s) to any current positional parameters.

Please don't use eval for something like this. setwill keep the integrity of the parameters and commands other than echowill play nicely with them. Just keep in mind you'll lose the reference(s) to any current positional parameters.

set -- "a b" "c"
echo "$@"
#a b c
echo 
#a b
echo 
#c

回答by Roland Illig

X="'a b' 'c'"
echo $X
eval "echo $X"

When you use this code you have to be careful if Xcan possibly contain special characters like \"$or backticks.

When you use this code you have to be careful if Xcan possibly contain special characters like \"$or backticks.

回答by jfg956

Are you sure echoreceives a 2 parameters in echo $X? For me, it receives 3. Lets try:

Are you sure echoreceives a 2 parameters in echo $X? For me, it receives 3. Lets try:

X="'a b' 'c'"
function f(){ echo $#; echo ; echo ; echo ; }
f $X

displays:

displays:

3
'a
b'
'c'

The 3 parameters are 'a, b'and 'c'. I do not think it is what you expect.

The 3 parameters are 'a, b'and 'c'. I do not think it is what you expect.

If you want to build a multi parameter variable, set IFS to a char you will not use (maybe |), and use it as a parameter delimiter in your variable:

If you want to build a multi parameter variable, set IFS to a char you will not use (maybe |), and use it as a parameter delimiter in your variable:

X="a b|c"
IFS="|"
function f(){ echo $#; echo ; echo ; }
f $X

回答by C. Ramseyer

This is hairy, I'd recommend working around the issue and don't concatenate "a b" and "c" in the first place.

This is hairy, I'd recommend working around the issue and don't concatenate "a b" and "c" in the first place.