Bash 打印除 first 之外的所有参数 - print 返回文件名

Bash print all arguments except first - print returns file names

提问人:zeroweb 提问时间:9/16/2020 最后编辑:Cyruszeroweb 更新时间:9/16/2020 访问量:684

问:

我有一个 bash 脚本,它应该在两行中打印参数。第一行应该是第一个参数,第二行应该是其余的参数

#!/bin/bash

FIRST_ARG="$1"
shift
REST_ARGS="$@"

echo $FIRST_ARG
echo $REST_ARGS

这适用于普通参数,例如

root@us:~# /bin/bash parse.sh testName test1 test2 test3
testName
test1 test2 test3
root@us:~# 

但是,我想要的是发送一个键值对作为参数,例如

testName "X-Api-Key: 1be0ad48" "Name: someTest" "Interval: * * * * *"

我希望这会产生如下结果

testName
"X-Api-Key: 1be0ad48" "Name: someTest" "Interval: * * * * *"

包括引号。但是,我得到了以下结果

root@us:~# /bin/bash parse.sh testName "X-Api-Key: 1be0ad48" "Name: someTest" "Interval: * * * * *"
testName
X-Api-Key: 1be0ad48 Name: someTest Interval: parse.sh parse.sh parse.sh parse.sh parse.sh
root@us:~# 

这里发生了两件我不想要的事情。1)它删除了引号“,2)它用文件名替换了*。

我试图用“逃避那些,但它没有用。有没有办法解决这个问题?我哪里做错了?

bash shell 参数 引号

评论

0赞 Gordon Davisson 9/16/2020
在将参数传递给脚本之前,引号会被删除,因此您想要的实际上是不可能的。但根据您想要报价的原因,有可能实现您的实际目标。“在 bash 参数中保留引号”的答案有帮助吗?
0赞 glenn jackman 9/16/2020
序言中有一个非常详尽的解释,可以接受 unix.stackexchange.com/q/171346/4667
0赞 William Pursell 9/16/2020
无论是写还是 ,cmd 都会使用相同的参数调用,并且这些参数中没有引号。它们只是字符串和 .cmd a bcmd "a" "b"ab

答:

0赞 MarcoLucidi 9/16/2020 #1

被扩展,因为你正在做一个没有引号的.尝试添加如下引号:*echo$REST_ARGS

#!/bin/bash

FIRST_ARG="$1"
shift
REST_ARGS="$@"

echo "$FIRST_ARG"
echo "$REST_ARGS"

保留双引号的解决方案是使用单引号引用字符串,如下所示:'

$ bash parse.sh testName '"X-Api-Key: 1be0ad48"' '"Name: someTest"' '"Interval: * * * * *"'
testName
"X-Api-Key: 1be0ad48" "Name: someTest" "Interval: * * * * *"
$

评论

1赞 glenn jackman 9/16/2020
这仍然将其余的参数存储为 REST_ARGS 变量中的单个字符串,尽管您已经保护了单词拆分和路径名扩展。通常,在参数中存储文本引号是一个坏主意:将参数传递给的命令必须处理文本引用,否则会引发错误
0赞 MarcoLucidi 9/16/2020
在这种特殊情况下,@glennjackman是一个问题?我同意在参数中存储引号是一个坏主意,但我从问题中了解到 OP 想要保留它们。That still stores the rest of the args as a single string in the REST_ARGS variable
1赞 glenn jackman 9/16/2020 #2

隐藏命令行参数的唯一可靠方法是在数组中:

#!/bin/bash

first_arg="$1"
shift
rest_args=("$@")
# ........^....^

# show how bash has stored these variables
declare -p first_arg
declare -p rest_args

echo "first = $first_arg"
for arg in "${rest_args[@]}"; do
    echo "arg = $arg"
done

摒弃使用 ALLCAPS 变量名的习惯,将其保留为 shell 保留的名称。有一天你会写,然后想知道为什么你的剧本被破坏了PATH=something

0赞 Léa Gris 9/16/2020 #3

你要求的:

#!/usr/bin/env sh

echo "$1"
shift
printf '"%s" ' "$@"
# or alternatively:
# env printf '%q ' "$@"
echo