Bash while循环中不记得修改变量

Bash while循环中不记得修改变量,bash,shell,while-loop,Bash,Shell,While Loop,我试着询问人们哪些接口用作iptables上的公共接口: while循环不记得变量,我真的不知道为什么 #!/bin/sh ### Show all available interfaces and configure to use them in while-loop: # Here is the answer of the function: # "${PUB_IF}" != "eth0" -a "${PUB_IF}" != "eth1" -a "${PUB_IF}" != "vmbr

我试着询问人们哪些接口用作iptables上的公共接口: while循环不记得变量,我真的不知道为什么

  #!/bin/sh
### Show all available interfaces and configure to use them in while-loop:
# Here is the answer of the function: 
# "${PUB_IF}" != "eth0" -a "${PUB_IF}" != "eth1" -a "${PUB_IF}" != "vmbr0"
function good_interfaces() {
ip a | grep '^[0-9]:' | grep -v 'lo' | awk '{ print $2 }' | sed -e 's/^/"/' -e 's/:$/"/' -e '/$/ i\-a "${PUB_IF}" !=' | sed '$!N; s/\n/ /g' | tr '\n' ' ' | awk 'sub("^...", "")'
}

### Show available interfaces
# Here is the answer of "echo ${IF_LIST}"
# eth0? eth1? vmbr0?
IF_LIST=$(ip a | grep '^[0-9]:' | grep -v 'lo' | awk '{ print $2 }' | sed 's/:/\?/g' | tr '\n' ' ')

while [ $(good_interfaces) ]; do
# When i replace $(good_interfaces) by its answer, the loop works: 
# while [ "${PUB_IF}" != "eth0" -a "${PUB_IF}" != "eth1" -a "${PUB_IF}" != "vmbr0" ] --> without the variable it works but isn't personalized for all machines
  echo "${IF_LIST}"
  read -p "Enter the interface to use: " PUB_IF
done;
以下是ip a的
答案:

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq master vmbr0 state UP group default qlen 1000
    link/ether xx:xx:xx:xx:xx:xx brd ff:ff:ff:ff:ff:ff
    inet x.x.x.x/x brd x.x.x.x scope global eth0
       valid_lft forever preferred_lft forever
3: eth1: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc mq state DOWN group default qlen 1000
    link/ether xx:xx:xx:xx:xx:xx brd ff:ff:ff:ff:ff:ff
1:lo:mtu 65536 qdisc noqueue状态未知组默认值
链接/环回00:00:00:00:00 brd 00:00:00:00:00:00:00
inet 127.0.0.1/8范围主机lo
永远有效\u lft首选\u lft永远有效
inet6::1/128作用域主机
永远有效\u lft首选\u lft永远有效
2:eth0:mtu 1500 qdisc mq主vmbr0状态更新组默认qlen 1000
链路/以太网xx:xx:xx:xx:xx:xx brd ff:ff:ff:ff:ff:ff
inet x.x.x.x/x brd x.x.x.x范围全局eth0
永远有效\u lft首选\u lft永远有效
3:eth1:mtu 1500 qdisc mq状态关闭组默认qlen 1000
链路/以太网xx:xx:xx:xx:xx:xx brd ff:ff:ff:ff:ff:ff

首先对您的代码发表一些评论:

  • #/bin/sh

    删除此行上的空格(并使用bash)。现在这行只是评论
  • ip a|grep'^[0-9]:“|grep-v'lo”|更多

    对不起,命令越来越复杂了。当你看不到输入时,你认为你能在两个月内自己理解它吗
  • IF_LIST=$(ip a | grep'^[0-9]:'| grep-v'lo'及更多)

    一些代码与函数good_interfaces共享
  • while[$(良好的接口)];执行

    while循环需要一个true/false表达式,您希望函数返回的字符串将被视为一个表达式
那么,您应该如何实现读取PUB_IF并在有效时中断的构造呢

将所有有效接口放入带有清晰分隔符的字符串中(我将使用空格)。 我将在字符串前后添加一个空格,以便以后进行匹配。
要一个酒吧,然后检查一下

valid_interfaces=" eth0 eth1 vmbr0 "
PUB_IF=""
# Edit: changed "while [ true ]; do" into "while true; do"
while true; do
   read -p "Enter the interface to use: " PUB_IF
   if [[ "${valid_interfaces}" = *;${PUB_IF};* ]]; then
      echo "${PUB_IF} is valid"
      break
   else
      echo "Nope, please enter something like${valid_interfaces}"
   fi
done 
另一个问题是如何找到有效的接口。使用剪切:

valid_interfaces=" $(ip a | grep ": <" | grep -v "lo" | cut -d: -f2 | tr '\n' ' ')

valid_interfaces=“$(ip a | grep”:查看序列
grep…| grep-v…| awk…| sed…
应该是一个命令-可能是
awk
,但现在很有可能您可以使用
sed
grep
来代替。无论如何,不需要将四个命令排成一行。即使没有这一点,您也可以将序列放入一个函数中您不必重复。这样我们就有机会理解您的问题。我假设原始代码中不存在
unset PIB_IF
。如果存在,则为
-z“${PUB_IF}”
测试是多余的-它是未设置的,因此总是计为零长度。循环中设置的变量在循环后不会被记住的正常原因是循环在子外壳中运行。这不是所示代码中的问题。您能否显示
ip a的三行或四行输出?一行用于
lo接口和至少两个其他接口,以便我们这些机器上没有
ip
命令的人可以看到您正在处理的数据是什么样子的?谢谢您的帮助。我用函数修改了代码。所以您认为如果我只在一个命令中修改序列
grep…| sed…| awk…
,它会工作吗?问题是我来自管道的?我正在处理序列的单个命令。如果代码中不存在unset PUB_,我将直接在shell中测试代码,因此我必须取消设置变量。您希望
为true;do
而不是
while[true];do
。即使它们在功能上是等效的,
[true]
为true是因为括号中的字符串不是空的,不是因为它正在运行
true
命令。@Glenn谢谢,非常正确。即使
while[false]
是真的。@Walter谢谢!!你说得对,我真的不知道我怎么只关注这个方法。你的方法简单多了!!所以不可能把函数放在while循环中,因为while不会把它看作一个表达式?没有什么能解决这个“问题”?我试过你的代码和部分
if[[“${valid\u interfaces}=*;${PUB\u if};*];然后,
在我的机器上不工作。结果如下:
sh test;输入要使用的接口:eth test:6:test:[[:未找到测试:6:test:eth:not found eth有效
@Walter,我终于使用了您的构造:
while[-z$I];do read-p“输入要使用的接口($valid\u interfaces)”PUB_IF;for IF in${valid_interfaces};do[“${IF}”=${PUB_IF}]和&{i=1;break;};done;done
${PUB_IF}
上进行测试时,只要在
read-p
上按enter键就可以了。当然,可以使用
“${PUB_IF}”
。我的代码中没有,但我使用的是
[..]
,它的工作原理与
]
。当您的解决方案起作用时,您可以接受此答案。