【问题标题】:Bash - function with optional arguments and missing logicBash - 带有可选参数和缺少逻辑的函数
【发布时间】:2012-10-23 18:23:14
【问题描述】:

我正在尝试为 useradd 命令创建简单的函数并快速提高我糟糕的 shell 编程技能。

useradd -m -g [initial_group] -G [additional_groups] -s [login_shell] [username]

现在我有点不确定如何使用可选参数。经过一些谷歌搜索,我认为可能已经掌握了这一点,只需要玩弄代码。

我不确定的一件事是逻辑,我很好奇你们会如何写这篇文章。我相信它会比我可以一起破解的更好。


下面是我尝试设置函数参数的方法,对于登录 shell 和初始组,我希望它们具有通用默认值。

arg1 - userName, required
arg2 - loginShell, optional (default: /bin/bash)
arg3 - initGroup, optional (default: users)
arg4 - otherGroups, optional (default: none)

这是一些蹩脚的伪代码,说明我是如何构造它的。

function addUser( userName, loginShell, initGroup, otherGroups){
// Not how I would go about this but you should get the point
  string bashCmd = "useradd -m -g ";

// Adding the initial user group
  if(initGroup == null){
    bashCmd += "users";
  } else {
    bashCmd += initGrop;
  }

// Adding any additional groups
  if(otherGropus != null){
    bashCmd += " -G " + otherGroups;
  }

  if(loginShell == null){
    bashCmd += " -s /bin/bash " + userName;
  } else {
    bashCmd += " -s " + loginShell + " " + userName;
  }
}

这些是我要去的链接

http://tldp.org/HOWTO/Bash-Prog-Intro-HOWTO-8.html

Passing parameters to a Bash function

How to write a bash script that takes optional input arguments?

Using Functions inside here document

【问题讨论】:

    标签: bash


    【解决方案1】:

    您可能会发现${parameter:+word} 扩展很有用。来自Bash Reference Manual

    如果parameter 为null 或未设置,则不替换任何内容,否则替换word 的扩展。

    所以:

    function addUser {
        useradd -m ${2:+-s "$2"} ${3:+-g "$3"} ${4:+-G "$4"} "$1"
    }
    

    请注意,如果任何参数包含有趣的字符(如空格、美元符号或其他 shell 元字符),此函数会正确处理引用。如果您尝试将命令字符串拼凑在一起,则正确引用这些片段要困难得多。如果这只是供您个人短期使用并且您知道输入是安全的,那可能并不重要。但是,如果脚本或函数打算以 root 身份运行并且没有非常仔细地处理其输入,那么最好不要留下任何脚本或函数。

    【讨论】:

    • 谢谢,验证输入真的不是问题,因为我正在做随机的 fooBar 帐户,我的 Java 太多了
    【解决方案2】:

    @rob mayoff 的回答是完成此任务的最简单方法,但我想我会尝试将您的伪代码转换为真正的 shell 语法,以指出一些习惯于“真正”编程语言的人的标准陷阱。先说三个一般注意事项:

    • 不同的 shell 具有不同的功能,因此如果您需要任何 bash 扩展,请使用 bash(即使用 #!/bin/bash 启动脚本或使用 bash 命令运行它)。如果您只使用基本的 Bourne shell 功能和语法,请改用 sh(#!/bin/shsh 命令)运行它。如果您不知道,假设您需要 bash。
    • 在构建稍后执行的命令时,您可能会遇到各种解析异常(请参阅BashFAQ#050: I'm trying to put a command in a variable, but the complex cases always fail!)。最好的方法通常是将其构建为数组,而不是字符串。 '当然,数组是 bash 扩展,而不是基本的 shell 功能......
    • 在 shell 语法中,空格很重要。例如,在命令if [ -n "$2" ]; then 中,分号后面的空格是可选的(分号之前也可以有一个空格),但是all 其他空格是必需的(没有它们的命令会做一些完全不同的事情)。此外,在作业中,等号周围不能有空格,或者(再次)它会做一些完全不同的事情。

    考虑到这一点,这是我对该功能的看法:

    addUser() {
    # The function keyword is optional and nonstandard, just leave it off. Also,
    # shell functions don't declare their arguments, they just parse them later
    # as $1, $2, etc
    
    bashCmd=(useradd -m)
    # you don't have to declare variable types, just assign to them -- the
    # parentheses make this an array. Also, you don't need semicolons at the
    # end of a line (only use them if you're putting another command on the
    # same line). Also, you don't need quotes around literal strings, because
    # everything is a string by default. The only reason you need quotes is to
    # prevent/limit unwanted parsing of various shell metacharacters and such.
    
    # Adding the initial user group
    if [ -z "$3" ]; then
    # [ is actually a command (a synonym for test), so it has some ... parsing
    # oddities. The -z operator checks whether a string is empty (zero-length).
    # The double-quotes around the string to be tested are required in this case,
    # since otherwise if it's zero-length it'll simply vanish. Actually, you
    # should almost always have variables in double-quotes to prevent accidental
    # extra parsing.
    # BTW, since this is a bash script, we could use [[ ]] instead, which has
    # somewhat cleaner syntax, but I'm demonstrating the difficult case here.
        bashCmd+=(-g users)
    else
        bashCmd+=(-g "$3")
        # Here, double-quotes here are not required, but a good idea in case
        # the third argument happens to contain any shell metacharacters --
        # double-quotes prevent them from being interpreted here. -g doesn't
        # have any shell metacharacters, so putting quotes around it is not
        # necessary (but wouldn't be harmful either).
    fi
    
    # Adding any additional groups
    if [ -n "$4" ]; then
        bashCmd+=(-G "$4")
    fi
    
    # Set the login shell
    if [ -z "$2" ]; then
        bashCmd+=(-s /bin/bash "$1")
    else
        bashCmd+=(-s "$2" "$1")
    fi
    
    # Finally, run the command
    "${bashCmd[@]}"
    # This is the standard idiom for expanding an array, treating each element
    # as a shell word.
    }
    

    【讨论】:

    • 如果遗漏任何可选参数,这不会中断吗?例如,如果调用者没有指定 loginShell,但指定了 initGroup 和 otherGroups,则该函数会将 initGroup 误解为 loginShell(因为它是第二个参数),而将 otherGroups 解释为 initGroup(因为它是第三个参数)。
    • @dg99 在这种情况下,您需要传递一个空字符串作为缺少的参数以避免混淆。例如:addUser fred "" someGroup anotherGroup 会将空字符串传递为$2,将“someGroup”传递为$3,将“anotherGroup”传递为$4
    【解决方案3】:

    google for ABS 获取许多复杂样本

    function addUser{
    userName=$1;
    loginShell=$2;
    initGroup=$3
    otherGroups=$4;
    
      args=(-m -g);
    
    // Adding the initial user group
      if [[ $initGroup == '' ];then
        args+=(users);
      else 
        args+=("$initGrop");
      fi;
    
    # Adding any additional groups
      if [[ $otherGroups != '' ]];then
        args+=(-G "$otherGroups");
      fi;
    
      if [[ $loginShell == '' ]];then
        args+=(-s /bin/bash "$userName");
      else
        args+=(-s "$loginShell" "$userName");
      fi;
      useradd "${args[@]}"
    }
    

    代码没有检查,但我希望我不会错过任何东西

    【讨论】:

    • 代码未检查,但我希望我不会错过任何内容这是示例,如何获取选项
    • 建设性评论: 1. 不要在= 中留下空格:例如,在bashCmd = $bashCmd"users" 行中,Bash 尝试使用参数bashCmd 执行命令bashCmd 和@ 987654328@ 扩展为。 2. Don't put your commands in a variable! 使用数组代替。 3. string 很可能是command not found 4. 错字otherGropus 而不是otherGroups。 5. ABS 并不是一个很好的参考!它在 Bash 程序员中的名声很差(看,你提到它并且你给出了一个糟糕的答案)。无意冒犯:)
    • 最大的问题是原始问题 :) 但是好的,我会解决你的满意,关于 ABC,我只是没有看到更好的 bash 学习指南(比如 iptables-howto,o'c it不是最好的,x-tables 比它们多得多,但提供了很好的介绍),所以我认为这更多的是关于完美的,谢谢你的评论。
    猜你喜欢
    • 2013-05-26
    • 1970-01-01
    • 1970-01-01
    • 2021-09-02
    • 2012-06-05
    • 2011-04-28
    • 2020-12-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多