【问题标题】:Parse Strings in HIVE using Shell使用 Shell 在 HIVE 中解析字符串
【发布时间】:2021-09-05 20:48:53
【问题描述】:

我有一个 shell 脚本,用于将字符串变量解析到 Hive 中,以过滤我的观察结果。我在下面提供了脚本和配置单元代码。

在以下脚本中,我有一个具有字符串值的变量,我尝试将其解析为配置单元,如下示例:

Shell 脚本:

name1='"Maria Nash"' *(I use a single quote first and then a double)*

hive --hiveconf name=${name1} -f t2.hql

Hive 代码 (t2.hql)

create table db.mytable as

SELECT *

FROM db.employees

WHERE emp_name='${hivevar:name}';

结论

准确地说,最终表已创建,但不包含任何观察结果。 employees 表包含但 emp_name 为“Maria Nash”的观察结果。

我认为我可能无法从 shell 正确解析字符串,或者我没有遵循正确的语法来处理配置单元查询中的解析变量。

感谢您的帮助!

【问题讨论】:

  • 你为什么用单引号+双引号。双引号就够了。当传递给 Hive 并且在 Hive 中添加单引号时,它们将被删除,这是正确的。还是您的 emp_name 包含双引号?
  • @leftjoin 请再次检查我的示例。我改变了它。我用“Maria Nash”之类的字符串替换了“Maria”。可能会有所不同。
  • 引号由shell处理,但是当您在带引号的表达式中使用引号时,它们是字符串值的一部分,您可以使用例如name1='Maria Nash'然后hive --hiveconf name="${name1}" -f t2.hql,双引号对于参数扩展很重要,问题是使用不带引号的name=${name1}
  • @NahuelFouilleul 这是正确的答案。谢谢!
  • 将此添加为 Hive 脚本的第一行:` ! echo emp_name='${hivevar:name}'` - 空格+!是从 Hive 执行的 shell 命令。这将打印您的参数

标签: bash shell hadoop hive


【解决方案1】:

您在hiveconf 命名空间中传递变量,但在sql 脚本中使用hivevar,您还应该使用hiveconf

WHERE emp_name=${hiveconf:name} --hiveconf, not hivevar

【讨论】:

    【解决方案2】:

    CLI 的使用是deprecated

    你可以使用 shell 脚本中的直线

    它应该看起来像

    beeline << EOF
    
    !connect jdbc:hive2://host:port/db username password
    
    select * 
    from db.employees
    where emp_name = "${1}"
    
    EOF
    

    假设 $1 是脚本的输入。

    这是一个如何做到这一点的示例,而不是生产实现。一般来说,

    1. 将启用 Kerberos,因此用户名和密码将不存在 并且可以使用有效的令牌
    2. 验证输入参数。

    考虑到你可以在一行中完成

    beeline -u jdbc:hive2://hostname:10000  -f {full Path to Script} --hivevar {variable}={value}
    

    【讨论】:

    • 这是一个等待发生的 SQL 注入攻击。您没有将值传递给查询;您正在动态构造来自变量的查询,该变量可能包含任意 SQL 片段。
    • 已更改,但这通常取决于您如何将参数传递到脚本中
    • 问题是where emp_name = "${1}"。假设$11; drop table db.employeesbeeline 看到的查询现在是 select * from db.employees where emp_name = 1; drop table db.employees,而不是 select * from db.employees where emp_name = '1; drop table db.employees'
    • 但是对于没有任何字段验证的任何参数化脚本都是如此,我明白你的意思,但它看起来有点迟钝。您可以通过添加字段验证来改进我的答案。
    • 这个想法是您不要在bash 中构造查询。我不知道beeline 的功能是什么,但假设您可以这样称呼它:beeline 'select * from db.employees where emp_name = %s' "$1"。现在 you 没有构建查询;您告诉beeline 获取$1 的值并将其插入到%s 所在的查询中,但安全 这样您就不会混合代码和数据。
    猜你喜欢
    • 1970-01-01
    • 2012-02-26
    • 1970-01-01
    • 1970-01-01
    • 2019-05-03
    • 1970-01-01
    • 2023-03-08
    • 1970-01-01
    • 2013-01-08
    相关资源
    最近更新 更多