在Shell脚本中使用$ *

时间:2018-12-26 16:27:51

标签: bash shell

我有一个非常简单的脚本,其中我根据传递到脚本中的文本(任何电子邮件)分配变量。无论采用哪种方式,我都将前两个语句放在第一个起作用。括号中的两个表达式都独立于CLI起作用。

Var1=$(grep 'Message-ID: <' $* | awk -F: '{print $2}' | tr -d "<> " )
Var2=$(grep 'Subject: ' $* | awk -F: '{print $2}' )

## only Var1 works

Var2=$(grep 'Subject: ' $* | awk -F: '{print $2}' )
Var1=$(grep 'Message-ID: <' $* | awk -F: '{print $2}' | tr -d "<> " )

## only Var2 works

我认为我缺少一些基本知识 $ *表达式。在任何bash文档中都无法找到清晰的信息。

非常感谢初学者的帮助。

1 个答案:

答案 0 :(得分:3)

初始上下文:在$@$*

这两个都引用脚本的自变量。因此,期望您的脚本本身将使用一个或多个文件名传递,并且应该搜索这些文件以查找电子邮件标头。

但是,$*这样做的方式完全不适合当前的目的;只能使用"$@"


使用$*扩展到文件名

使用$*扩展到文件名列表是总是错误的,应该从不进行。其操作如下:

  • 脚本自变量列表中的项目被连接成一个字符串,并用$IFS中的第一个字符分隔(默认情况下为空格)。
  • 该字符串在IFS中的所有个字符上拆分-由连接添加的空格被拆分出来,并且参数之间的空格也被 断开以得到单个单词的列表。
  • 这些单词中的每个单词都被作为全局表达式处理,例如用当前目录中的文件列表替换*单词。

如果要将脚本的参数列表传递给grep,请使用"$@"从不使用$*,除非您明确希望将参数连接在一起成为单个字符串。


关于从电子邮件中提取标题

您可以仅使用awk从电子邮件中提取消息ID,如下所述(为了清楚起见,分成多行):

messageId=$(awk -F: '
$1 == "Message-Id" {                 # Match fields where the first field is message-id
  gsub("^[[:space:]]*[<]", "", $2);  # Remove space and < from the beginning (only!)
  gsub("[>]$", "", $2);              # Remove > from the end
  print $2;                          # Print result
  exit(0);                           # exit to avoid more spurious matches later
}' "$@" </dev/null)

这个主题更加容易,下面的内容可以正确处理带有冒号的主题(任何依赖awk -F: 的):

subject=$(awk '/^Subject:/ { gsub("^Subject:[[:space:]]+", ""); print $0 }' "$@" </dev/null)

使用</dev/null可确保即使"$@"为空(因此没有参数),我们也不会挂起。