我有一个变量,其中包含 crontab 中的一行
例如:
0 22 * * 1-5 echo hello
我想将其分为 2 个变量,一个变量用数字或星号表示作业的周期,另一个变量用作业运行时要执行的命令。
所以我需要找到一种方法在第一次出现字母字符时分割字符串,但我不知道如何做到这一点。
答案1
这并不完全是您正在寻找的,但应该适合您的用例。将该行读入六个变量,并按变量定义的空格和制表符分隔IFS
。
修改后的 crontab 条目的示例:
$ line='0 22 * * 1-5 echo "foo bar baz"'
$ IFS=$'\t ' read -r a b c d e cmd <<<"$line"
$ echo "$a $b $c $d $e"
0 22 * * 1-5
$ echo "$cmd"
echo "foo bar baz"
请注意,前五个字段中的多个空格(或制表符)被压缩为一个空格字符,但命令中的空格/制表符保持不变。"$a $b $c $d $e"
如果需要,您可以分配给单个变量。
答案2
答案3
我认为您可以使用 来执行此操作awk
,特别是因为您的标签表明您想在 shell 脚本中使用它。看一下下面的代码片段,我将像其他回复者一样,为参数分配一个 bash 变量,其中包含您可能处理的内容:
#!/bin/bash
# fill 'line' with example content
line='0 22 * * 1-5 echo foo bar baz -o outfile.txt *'
# split 'line' into "scheduling" and "command" part:
SCHED=$(awk '{match($0, "^([0-9* -]*)([[:print:]]*)", a); print a[1]}' <<< "$line")
echo "$SCHED"
CMD=$(awk '{match($0, "^([0-9* -]*)([[:print:]]*)", a); print a[2]}' <<< "$line")
echo "$CMD"
如果你测试这个,它应该输出
user@host $ ./split_test.sh
0 22 * * 1-5
echo foo bar baz -o outfile.txt *
解释
- 在执行实际“拆分”的两行中,我将左侧的变量分配为该
$( ... )
部分中命令的输出(参见例如高级 Bash 脚本编写指南例如),其中我输入变量的内容,通过双括号( ')$line
防止通配符(这样,除其他外,空白被“按原样”保留)。" ... "
awk
- 该
awk
调用使用内部match()
函数来查找字符串中的特定模式,在我们的例子中,( ... )
行开头的一组包含数字、星号、空格和破折号的任意组合,数量不限,后跟一组包含任何可打印字符,数量也不受限制。由于正则表达式是贪婪的,因此两个部分都将通过最长的可能子字符串进行匹配,因此第 1 组实际上会继续下去,直到./
找到第一个不适合其中的字符(即第一个字母数字字符,甚至 )。第二组只是该行的剩余部分,并且可以包含所有可打印字符,包括数字和特殊字符。 - 使用
awk
smatch
函数背后的想法是,如果您通过将子组括在括号中来指定子组,则可以指示awk
将模式的实际值填充到数组中,在本例中a
,这样a[1]
包含 的实际值组 1(“调度”部分)和a[2]
组 2(“命令”部分)的实际值。 - 虽然有点不优雅,但我们应用了两次,
awk
在第一次调用中输出第一部分,在第二次调用中输出第二部分,以将值分配给单独的 bash 变量。
如果你想了解更多这方面的知识,你可以看看GNU Awk 用户指南。
答案4
您可以使用 cut 来分隔由空格分隔的值,如下所示:
#/bin/sh
var='0 22 * * 1-5 echo hello'
first=$(echo -n "$var" | cut -d' ' -f1)
second=$(echo -n "$var" | cut -d' ' -f2)
third=$(echo -n "$var" | cut -d' ' -f3)
fourth=$(echo -n "$var" | cut -d' ' -f4)
fifth=$(echo -n "$var" | cut -d' ' -f5)
restofvar=$(echo -n "$var" | cut -d' ' -f6,7)
E:正如评论中指出的,如果字符串中有多个空格,则必须将它们替换为单个空格:
var=$(echo "$var" | tr -s " ")