Bash - 带有可选参数和缺少逻辑的函数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13206311/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 03:41:21  来源:igfitidea点击:

Bash - function with optional arguments and missing logic

bash

提问by Dan

I'm trying make simple function for the useradd command and to quickly improve my poor shell programming skills.

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

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

Right now I'm somewhat unsure how to function with optional arguments. After some Googling and I think might have a handle on that, just need to play around the code.

现在我有点不确定如何使用可选参数运行。经过一些谷歌搜索,我认为可能会解决这个问题,只需要玩转代码。

One thing that I'm unsure about is the logic and I'm curious on how you guys would go about writing this. I'm sure it will be better then what I could hack together.

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



Here is how I going to try setup my function arguments, for the login shell and the initial group I would them to have generic defaults.

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

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

This is some lame pseudo code on how I'm thinking to structure this.

这是关于我正在考虑如何构建它的一些蹩脚的伪代码。

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;
  }
}


These are the links I'm going by

这些是我要去的链接

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

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

Passing parameters to a Bash function

将参数传递给 Bash 函数

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

如何编写带有可选输入参数的 bash 脚本?

Using Functions inside here document

在此处文档中使用函数

回答by rob mayoff

You might find the ${parameter:+word}expansion useful. From the Bash Reference Manual:

您可能会发现${parameter:+word}扩展很有用。来自Bash 参考手册

If parameteris null or unset, nothing is substituted, otherwise the expansion of wordis substituted.

如果参数为空或未设置,则不替换任何内容,否则替换单词的扩展。

So:

所以:

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

Note that this function handles quoting properly if any of the arguments contain funny characters (like spaces, dollar signs, or other shell metacharacters). If you attempt to piece together a command string, it's much harder to quote the pieces properly. That might not matter if this is just for your personal, short-term use and you know the input is safe. But it's best not to leave a script or function lying around if it is intended to be run as root and doesn't handle its input very carefully.

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

回答by Gordon Davisson

@rob mayoff's answer is the simplest way to accomplish this, but I thought I'd take a stab at turning your pseudo code into real shell syntax to point out some standard gotchas for people used to "real" programming languages. Three general notes first:

@rob mayoff 的回答是实现这一目标的最简单方法,但我想我会尝试将您的伪代码转换为真正的 shell 语法,以便为习惯于“真正”编程语言的人们指出一些标准问题。首先是三个一般注意事项:

  • Different shells have different capabilities, so use bash (i.e. start your script with #!/bin/bashor run it with the bashcommand) if you need any bash extensions. If you are only using basic Bourne shell features and syntax, run it with sh (#!/bin/shor the shcommand) instead. If you don't know, assume you need bash.
  • When building a command for later execution, there are all sorts of parsing oddities you can run into (see BashFAQ#050: I'm trying to put a command in a variable, but the complex cases always fail!). The best way is generally to build it as an array, rather than a string. 'Course, arrays are a bash extension, not a basic shell feature...
  • In shell syntax, spaces matter. For instance, in the command if [ -n "$2" ]; then, the space after the semicolon is optional (and there could also be a space before the semicolon), but allof the other spaces are required (without them the command will do something completely different). Also, in an assignment, there cannotbe spaces around the equal sign, or (again) it'll do something completely different.
  • 不同的 shell 具有不同的功能,因此如果您需要任何 bash 扩展,请使用 bash(即使用命令启动脚本#!/bin/bash或运行它bash)。如果您只使用基本的 Bourne shell 功能和语法,请改用sh(#!/bin/shsh命令)运行它。如果您不知道,请假设您需要 bash。
  • 在构建一个命令供以后执行时,您可能会遇到各种奇怪的解析(请参阅BashFAQ#050:我正在尝试将命令放入变量中,但复杂的情况总是失败!)。最好的方法通常是将其构建为数组,而不是字符串。'当然,数组是 bash 扩展,而不是基本的 shell 功能......
  • 在 shell 语法中,空格很重要。例如,在命令中if [ -n "$2" ]; then,分号后面的空格是可选的(分号前面也可以有一个空格),但所有其他空格都是必需的(没有它们,命令将执行完全不同的操作)。此外,在作业中,等号周围不能有空格,否则(再次)它会做一些完全不同的事情。

With that in mind, here's my take on the function:

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

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 , , 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 "" ]; 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 "")
    # 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 "" ]; then
    bashCmd+=(-G "")
fi

# Set the login shell
if [ -z "" ]; then
    bashCmd+=(-s /bin/bash "")
else
    bashCmd+=(-s "" "")
fi

# Finally, run the command
"${bashCmd[@]}"
# This is the standard idiom for expanding an array, treating each element
# as a shell word.
}

回答by zb'

google for ABSto get many complex samples

google for ABS获取很多复杂的样本

function addUser{
userName=;
loginShell=;
initGroup=
otherGroups=;

  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[@]}"
}

code not checked, but i hope i not miss anything

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