【问题标题】:"Ignore" quotes in positional parameters in my Bash script我的 Bash 脚本中位置参数中的“忽略”引号
【发布时间】:2015-12-03 15:57:20
【问题描述】:

我有一个将 SMS 转发给它的脚本,并将其中的一些数据发布到 PHP 脚本。下面是我的 Bash 脚本:

#!/bin/bash
# Script to post data to Top up processor
curl  --request POST 'http://127.0.0.1/user//topup/process.php' --data "receipt=$1" --data "username=$9"

所以运行它:

./mpesa_topup.sh sms_message

但是短信服务器用单引号转发消息:

./mpesa_topup.sh 'sms_message'

脚本最终“将整个 SMS 解析为 1 个位置参数。这是 sms 服务器运行脚本时发生的调试。

root@sms:/var/lib/playsms/sms_command/1# bash -x mpesa_topup.sh 'JJA88QHC22 Confirmed.on 101015 at 9:49 PMKsh25.00 received from 254712345678 SOME BODY.New Account balance is Ksh25.00'
+ curl --request POST http://10.5.1.2/topup/process.php --data 'receipt=JJA88QHC22 Confirmed.on 101015 at 9:49 PMKsh25.00 received from 254722227332 JOTHAM KIIRU.New Account balance is Ksh25.00' --data username=
root@sms:/var/lib/playsms/sms_command/1#

有没有办法删除/忽略 Bash 脚本中的开始和结束单引号?

PS : 我不是程序员,是在我的朋友 Google 的帮助下才走到今天的。

【问题讨论】:

  • 当你调用它时不要在它周围加上引号,如果你在调用命令时把它放在它周围,那么引号的意思是“把它当作一个参数”如果你不加引号, 分词发生分配位置参数
  • 当你 dbl 引用一个变量时,就像你对 --data "receipt=$1" 所做的那样,当你使用 shell 调试 (set -x) 时,shell “规范化”所有引用到它的“最终”表示执行,因此在调试输出中使用单引号。因此,如果您不想在 --data "receipt=$1" 周围出现任何引号,请删除它们。即使您在 $1 内使用 '\' 字符引用了转义空格,set -x 也会将该变量显示为带引号的单引号。祝你好运。

标签: linux bash shell curl


【解决方案1】:

您似乎想要发送给您的单个参数中的第一个和第九个单词。你可以这样做:

$ set --  'JJA88QHC22 Confirmed.on 101015 at 9:49 PMKsh25.00 received from 254712345678 SOME BODY.New Account balance is Ksh25.00'
$ echo $1
JJA88QHC22 Confirmed.on 101015 at 9:49 PMKsh25.00 received from 254712345678 SOME BODY.New Account balance is Ksh25.00

$ set -f      # a
$ set -- $1   # b
$ set +f      # c

$ echo $1
JJA88QHC22
$ echo $9
254712345678

关键是 (b) 我们在变量周围省略双引号。这允许 shell 对变量的值进行分词。

shell 还将尝试执行 glob 模式扩展,除非您告诉它不要这样做,我在 (a) 中执行此操作,然后在 (c) 中将其重新打开。

【讨论】:

  • 使用read 也适用于此。手动或使用-a。但所有这些解决方案都假设内部空间永远不会发生。
  • 成功了。谢谢。我现在有自动 WiFi 计费。我请你喝啤酒。
【解决方案2】:

您可以通过将主命令放入函数中并再次调用它来解决此问题。

您的服务器正在使用简单的引号调用您的脚本,这会将您的参数转换为一个参数 ($1)。

如果你处理这个 arg 并在脚本中调用 your_function(),你就解决了!

示例如下:

#!/bin/bash
# Script to post data to Top up processor
args=$1

your_function(){
  curl  --request POST 'http://127.0.0.1/user//topup/process.php' --data "receipt=$1" --data "username=$9"
  }
your_function $1

【讨论】:

  • 这似乎是一个很长的路要走,只是不首先引用参数列表,但我猜可以完成工作
  • 是的,埃里克,我同意.. 如果 mymanga 有权更改脚本的调用,您的“不引用”是最好的解决方案...我建议使用该功能,因为有时根 crontab 在高级服务器管理层是谁在调用......并且用户只能访问脚本本身......顺便说一句,两者都可以工作。感谢您的评论。
【解决方案3】:

是的,但这无济于事。最后,由于--data "receipt=$1",您的代码将整个短信作为单个字符串传递给curl。如果您只删除引号,那将变为 --data "receipt=JJA88QHC22",而其余部分(如金额)将丢失。

您的问题是输入是多行文本,并且以某种方式被破坏了。解决方案是解析短信。由于涉及金钱,您可能不希望出现任何错误。这就是为什么我会使用真正的编程语言,如 Python 或 Java。但如果你想使用 BASH,这可能会一直有效,直到攻击者开始向你发送 SMS 来窃取金钱:

# Split first parameter into $1...$n
set -- $1

recepient="$1"
# $2: Confirmed.on
# $3: 101015
# $4: at
# $5: 9:49
# $6: PMKsh25.00
amount=$(echo $6 | sed -e s/^(AM|PM)//) # sed removed the AM/PM at the beginning
# $7: received
# $8: from
sender="$7 $8 $9" # 254722227332 JOTHAM KIIRU.

【讨论】:

  • 谢谢亚伦。我正在使用 bash,因为这是 sms 服务器支持的。而且不用担心攻击者,因为我使用的是一个特殊的 SIM 卡,它只接收直接从电信公司付款的确认短信。我只需要将收据号码和电话号码转发到计费系统...这就是脚本如此简单的原因。只需要一种方法让它读取收据号码和电话号码。再说一遍..我不是编码员.. 几天来一直在谷歌上搜索我的位置。只需要让 bash 脚本忽略第一个和最后一个单引号 - mpesa.sh 'sms_message'
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-02-08
  • 2014-04-04
  • 2018-08-03
  • 1970-01-01
  • 2018-09-07
相关资源
最近更新 更多