bash 转义bash变量中的特殊字符
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9483171/
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
Escaping special characters in bash variables
提问by Andrei Ionita
I'm trying to read a file containing filepaths line by line and scp the files to another server, but because of certain characters in the filenames like '(', ')', '&' etc. I need to escape the input:
我正在尝试逐行读取包含文件路径的文件并将文件 scp 到另一台服务器,但由于文件名中的某些字符,如 '(', ')', '&' 等,我需要转义输入:
input.txt:
输入.txt:
/folder1/folderA/filename+(oh+how+nice,+parantheses)
script.sh:
脚本.sh:
#!/bin/sh
promote_to=random.server.com
dev_catalog=/folderX/
uat_catalog=/folderY/
while read line
do
uat_path=$(echo "$uat_catalog$line" | sed -e "s/(/\\(/g" | sed -e "s/)/\\)/g")
dev_path=$(echo "$dev_catalog$line" | sed -e "s/(/\\(/g" | sed -e "s/)/\\)/g")
scp $dev_path user@$promote_to:$uat_path
scp $dev_path".atr" user@$promote_to:$uat_path".atr"
done < "input.txt"
Output:
输出:
-bash: /folder1/folderA/filename+(oh+how+nice,+parantheses): No such file or directory
-bash: /folder1/folderA/filename+(oh+how+nice,+parantheses): No such file or directory
usage: scp [-1246BCpqrv] [-c cipher] [-F ssh_config] [-i identity_file]
[-l limit] [-o ssh_option] [-P port] [-S program]
[[user@]host1:]file1 [...] [[user@]host2:]file2
ssh: random.server.com: Name or service not known
lost connection
Any kind of help is appreciated.
任何形式的帮助表示赞赏。
回答by Gordon Davisson
Part of the problem here is that the local and remote filenames are parsed differently: the local filename is used directly, so the only thing you need to do is enclose it in double-quotes (as in @Ignacio's answer), but the remote filename gets passed to a remote shell which runs it through another layer of parsing (quote and escape removal, etc). So, you want to add escapes to the remote path only. I've also taken the liberty of simplifying the sed
command a little:
这里的部分问题是本地和远程文件名的解析方式不同:直接使用本地文件名,因此您唯一需要做的就是用双引号将其括起来(如@Ignacio 的回答),但远程文件名被传递到一个远程 shell,它通过另一层解析(引用和转义删除等)运行它。所以,你想逃脱添加到远程路径只。我还冒昧地简化了sed
命令:
#!/bin/sh
promote_to=random.server.com
dev_catalog=/folderX/
uat_catalog=/folderY/
while read line
do
uat_path="$(echo "$uat_catalog$line" | sed -e 's/[()&]/\&/g')"
dev_path="$dev_catalog$line"
scp "$dev_path" "user@$promote_to:$uat_path"
scp "$dev_path.atr" "user@$promote_to:$uat_path.atr"
done < "input.txt"
Note that the sed
pattern I used, 's/[()&]/\\&/g'
, only escapes parentheses and ampersands; if your filenames contain any other shell metacharacters, be sure to add them to the character list in []
.
请注意,sed
我使用的模式's/[()&]/\\&/g'
, 只转义括号和与号;如果您的文件名包含任何其他 shell 元字符,请务必将它们添加到[]
.
回答by Eduardo Ivanec
You're trying to execute /folder1/folderA/filename+(oh+how+nice,+parantheses)
as a command. You probably meant to do echo /folder1/folderA/filename+(oh+how+nice,+parantheses) | ...
instead.
您正在尝试/folder1/folderA/filename+(oh+how+nice,+parantheses)
作为命令执行。你可能打算这样做echo /folder1/folderA/filename+(oh+how+nice,+parantheses) | ...
。
Edit: what @Ignacio said.
编辑:@Ignacio 所说的。