【问题标题】:shell script input string with regular expression loop values带有正则表达式循环值的 shell 脚本输入字符串
【发布时间】:2012-09-19 22:14:26
【问题描述】:

我希望能够让用户输入:

./script.sh server[01-10]type

我已经得到了这个,并且可以与 [a-z] 或 [0-99] 一起使用,或者它的数值很高。虽然我真的不确定我是否以正确的方式去做,以及是否有更简单的方法来做同样的事情。

想检查是否有更简单的方法来做这样的事情,以及有多个通配符输入有多容易,例如:

./script.sh (server|web)[01-10][a-z]

然后它将解析 web01-10a-z 或 server01-10a-z 并列出所有服务器。

这是我目前所拥有的,我承认我需要整理它,但我想在专注于更整洁的代码调用之前让它更好地工作。

 #!/bin/bash
 input=$1;
 if [[ $input =~ \[ ]];then
     s="["
     f="]"
     host_start=`echo $input|awk -F"[" '{print $1}'`
     host_end=`echo $input|awk -F"]" '{print $2}'`
     start=`awk -v a="$input" -v b="$s" 'BEGIN{print index(a,b)}'`
     fin=`awk -v a="$input" -v b="$f" 'BEGIN{print index(a,b)}'`
     vals=`expr $fin - $start`
     ((start++))
     ((vals--))
     in1=`echo $input| awk -v s=$start -v f=$vals '{ print substr( $0, s($0),f($0) ) }'`
     val1=`echo $in1|awk -F"\-" '{print $1}'`
     val2=`echo $in1|awk -F"\-" '{print $2}'`
     for index in $(eval echo {$val1..$val2})
     do
         server="$host_start$index$host_end"
         echo "Current server: $server "
     done
fi

当我执行这个时,我得到:

./run.bash apache[9-11]
Current server: apache9 
Current server: apache10 
Current server: apache11 

$ ./run.bash apache[f-k]
Current server: apachef 
Current server: apacheg 
Current server: apacheh 
Current server: apachei 
Current server: apachej 
Current server: apachek 

$ ./run.bash apache[f-k]abc
Current server: apachefabc 
Current server: apachegabc 
Current server: apachehabc 
Current server: apacheiabc 
Current server: apachejabc 
Current server: apachekabc 

感谢大家的更新

3 行完成以上所有操作,并处理我想要的所有类型,方法如下:

#!/bin/bash
val=$1;

value=`echo "$val"|sed 's:(:{:g; s:):}:g; s:|:,:g; s/^//;s/$//'`
value=`echo "$value"|sed 's:\[:{:g; s:\]:}:g; s:-:\.\.:g; s/^//;s/$//'`
(eval echo $value)

./test-brace.sh "(server|apache)[0-2][a-c]"
server0a server0b server0c server1a server1b server1c server2a server2b server2c apache0a apache0b apache0c apache1a apache1b apache1c apache2a apache2b apache2c

【问题讨论】:

  • 预期输出是什么? in1awk 命令对我来说失败了,未定义的函数's'。
  • 顺便问一下,您是在尝试复制大括号扩展吗? echo {server,web}{01..10}{a..z}
  • 1.同意您需要向我们展示更多您的用例,即。输入和所需的输出。 2.您是否尝试生成所有可能的字符串,或者仅在服务器/资源实际存在时匹配? (使用此信息编辑您的问题)。 3.“想检查是否有更简单的方法”。您可能可以捕获所有 shell 变量 host*, start, fin, etc 并在 1 个 awk 脚本中打印输出。 4.也就是说,胆大妄为+1! 5.当你知道将其中的 80-90% 放入 1 个 awk 脚本是多么容易时,你就会真正学到一些东西。 6. 祝你好运!
  • 抱歉,尝试 #!/bin/bash 调用脚本,我将使用输出更新原始问题,但认为 chepner 的第二篇文章是我一直在寻找的。刚刚跑了回声线 - 这太棒了 Chepner :)
  • @chepner:将其添加为答案。

标签: regex bash shell brace-expansion


【解决方案1】:

您不需要脚本。你只需要大括号扩展:

echo {server,web}{01..10}{a..z}

for s in {server,web}{01..10}{a..z}; do
    echo Current Server: $s
done

【讨论】:

  • 谢谢,没有脚本的原因是因为它是对现有脚本的新要求,因此我将其放入其中。
  • 对不起,我猜“你不需要脚本”有点太强了。您只是不需要给定if 语句中的部分:)
  • 再次感谢,我现在已经更新了方法并很好地利用了它。 github.com/vahidhedayati/termssh 对于任何连接到多个服务器并想要一种简单的自动化连接方式的人 - 创建终结器(gnome)布局并启动与主机的连接
【解决方案2】:

除了其他答案之外,使用 fork 到 awk 让我觉得浪费了几百万个 CPU 周期。如果您只想删除 shell 变量中的一些子字符串,请使用这些 (POSIX) 修饰符:

$ foo=bar-baz-frob
$ echo ${foo%-*}    # Remove shortest match from the end
bar-baz
$ echo ${foo%%-*}   # Remove longest match from the end
bar
$ echo ${foo#*-}    # Remove shortest match at the beginning
baz-frob
$ echo ${foo##*-}   # Remove longest match at the beginning
frob
$

除了*? 还接受[0-9a-f] 范围,但不接受{} 的多重性。

如果你愿意交换你的 shell,zsh 可以通过大括号扩展来做到这一点:

zsh$ setopt BRACE_CCL
zsh$ echo {server,web}{01..10}{a-h}
server01a server01b server01c server01d server01e server01f server01g server01h 
server02a server02b server02c server02d server02e server02f server02g server02h 
server03a server03b server03c server03d server03e server03f server03g server03h 
server04a server04b server04c server04d server04e server04f server04g server04h 
server05a server05b server05c server05d server05e server05f server05g server05h 
server06a server06b server06c server06d server06e server06f server06g server06h 
server07a server07b server07c server07d server07e server07f server07g server07h 
server08a server08b server08c server08d server08e server08f server08g server08h 
server09a server09b server09c server09d server09e server09f server09g server09h 
server10a server10b server10c server10d server10e server10f server10g server10h 
web01a web01b web01c web01d web01e web01f web01g web01h web02a web02b web02c web02d 
web02e web02f web02g web02h web03a web03b web03c web03d web03e web03f web03g web03h 
web04a web04b web04c web04d web04e web04f web04g web04h web05a web05b web05c web05d 
web05e web05f web05g web05h web06a web06b web06c web06d web06e web06f web06g web06h 
web07a web07b web07c web07d web07e web07f web07g web07h web08a web08b web08c web08d 
web08e web08f web08g web08h web09a web09b web09c web09d web09e web09f web09g web09h
web10a web10b web10c web10d web10e web10f web10g web10h

我刚刚用 bash 试过了。略有不同:

echo {server,web}{01..10}{a..h}

【讨论】:

  • 非常酷,我过去曾使用过 foo##* 并且正在搞乱 % 但不太了解它 - 现在完全有意义了,谢谢
  • @vahid 血淋淋的细节可以在您的 shell 手册中找到,当然也可以在 POSIX 规范中找到,pubs.opengroup.org/onlinepubs/9699919799/utilities/… 如果您觉得我的回答有帮助,请考虑点赞;谢谢!
  • Bash 也有大括号扩展,因此无需切换到zsh(尽管zsh 确实有一些非常好的功能)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-10
相关资源
最近更新 更多