如果stdin中没有用户输入,则使bash脚本退出

时间:2017-02-23 17:24:08

标签: bash null stdin

我的bash脚本应该获得用户输入来处理退出的特定文件,如下所示:

import socket
import threading
from queue import Queue
import time

NUMBER_OF_THREADS = 2
JOB_NUMBER = [1,2]
queue = Queue()
all_connections = []
all_addresses = []

def socket_create():
try:

    global host
    global port
    global s
    host = ''
    port = 9999
    s = socket.socket()
except socket.error as msg:
    print("Socket creation error: " + str(msg))



def socket_bind():

try:
    global host
    global port
    global  s
    s.bind((host,port))
    s.listen(5)
except socket.error as msg:
    print("Socket binding error: " + str(msg))
    time.sleep(5)
    socket_bind()


def accept_connections():
for c in all_connections:
    c.close()
del all_connections[:]
del all_addresses[:]
while 1:
    try:
        conn, address = s.accept()
        conn.setblocking(1)
        all_connections.append(conn)
        all_addresses.append(address)
        print("\nConnection has been established: " + address[0])
    except:
         print("Errorr accepting connections")


def start_turtle():
while True:
    cmd = input('turtle> ')
    if cmd == 'list':
        list_connections()
    elif 'select' in cmd:
        conn = get_target(cmd)
        if conn is not None:
            send_target_commands(conn)

    else:
        print("Command not Recognized")



def list_connections():
results = ''
for i, conn in enumerate(all_connections):
    try:
        conn.send(str.encode(' '))
        conn.recv(20480)
    except:
        del all_connections[i]
        del all_addresses[i]
        continue
    results += str(i) + '   ' + str(all_addresses[i][0]) + '   ' + str(all_addresses[i][1]) + '\n'
    print('------ Clients -----' + '\n' + results)


def get_target(cmd):
try:
    target = cmd.replace('select ', '')
    target = int(target)
    conn = all_connections[target]
    print("You are now connected to " + str(all_addresses[target][0]))
    print(str(all_addresses[target][0]) + "> ", end = "")
    return conn
except:
    print("Now a valid selection")
    return None


def send_target_commands(conn):
while True:
    try:
        cmd = input()
        if len(str.encode(cmd)) > 0:
            conn.send(str.encode(cmd))
            client_response = str(conn.recv(20480), "utf-8")
            print(client_response, end="")
        if cmd == 'quit':
            break
    except:
        print("Connection was lost")
        break


def create_workers():
for _ in range(NUMBER_OF_THREADS):
    t = threading.Thread(target=work)
    t.daemon = True
    t.start()

def work():
while True:
    x = queue.get()
    if x == 1:
        socket_create()
        socket_bind()
        accept_connections()
    if x == 2:
        start_turtle()
        queue.task_done()
def create_jobs():
for x in JOB_NUMBER:
    queue.put(x)
    queue.join()

create_workers()
create_jobs()

此逻辑检查用户的输入:

if [ -e "formatted_log.csv" ]
then
    printf "\nPresence of formatted_log.csv file detected: It appears this script has already been run is this dir.\n"
    printf "Appending can cause errors.\n"
    read -e -p "Would you like to continue?[y/n]" stdin

问题在于,如果您只需按Enter键,脚本就会执行,就像" y"或者" Y"已经输入,我不知道为什么。我的理解是这样写的方式,如果用户放入y,Y,n或N以外的任何东西,它应该退出。

当您没有输入时,它会打印出来:

if [ $stdin = "n" ] || [ $stdin = "N" ];
then 
printf "\nOkay, exiting.\n"
exit;
fi
if [ $stdin != "y" ]&&[ $stdin != "Y" ]&&[ $stdin != "n" ]&&[ $stdin != "N" ]; 
then 
printf "\nPlease use a valid input (y/n)...exiting.\n"
exit;
    fi
fi

但是没有退出 - 我怎么能让它退出?

2 个答案:

答案 0 :(得分:3)

由于您已使用" Bash"对此进行了标记,因此您应该拥有更强大的[[ ]]运算符。然后你可以简化为这样的事情:

read stdin

if [[ $stdin == [Nn] ]]; then
    echo "Exiting"
    exit
fi

if [[ $stdin != [YyNn] ]]; then
    echo "Invalid input, exiting"
    exit
fi
==中的=(或!=)和[[ ]]执行模式匹配,因此您可以使用模式检查您的输入是否为有效,在[YyNn]等单个表达式中。

如果您想在用户输入有效内容之前询问输入,可以像这样循环:

while [[ $stdin != [YyNn] ]]; do
    read -p 'Continue? ' stdin
done

请注意,虽然在Bash中引用变量几乎总是好的做法,但您不必在[[ ]]内。如果你的模式是变量,它实际上不能被引用,或者它不被解释为模式。

答案 1 :(得分:2)

问题是 NOT 在变量$stdin周围加上引号,当引号不存在时,该引号不会保留空值,

例如,当变量为空时,[...]会看到如下表达式

+ '[' = n ']'
script.sh: line 9: [: =: unary operator expected
+ '[' = N ']'
script.sh: line 9: [: =: unary operator expected
+ '[' '!=' y ']'
script.sh: line 14: [: !=: unary operator expected
+ '[' 0 eq 0 ']'

您需要正确引用它们,以使其正常工作

9 if [ "$stdin" = "n" ] || [ "$stdin" = "N" ];

14  if [ "$stdin" != "y" ] && [ "$stdin" != "Y" ] && [ "$stdin" != "n" ] && [ "$stdin" != "N" ];

这样,按下回车键就可以安全地处理,

+ '[' '' = n ']'
+ '[' '' = N ']'
+ '[' '' '!=' y ']'
+ '[' '' '!=' Y ']'
+ '[' '' '!=' n ']'
+ '[' '' '!=' N ']'

以上更改运行完整脚本并在提示符下按 Enter ,在调试器模式下

 bash -x script.sh 
+ '[' -f file ']'
+ printf '\nPresence of formatted_log.csv file detected: It appears this script has already been run is this dir.\n'

Presence of formatted_log.csv file detected: It appears this script has already been run is this dir.
+ printf 'Appending can cause errors.\n'
Appending can cause errors.
+ read -e -p 'Would you like to continue?[y/n]' stdin
Would you like to continue?[y/n]
+ '[' '' = n ']'
+ '[' '' = N ']'
+ '[' '' '!=' y ']'
+ '[' '' '!=' Y ']'
+ '[' '' '!=' n ']'
+ '[' '' '!=' N ']'
+ printf '\nPlease use a valid input (y/n)...exiting.\n'

Please use a valid input (y/n)...exiting.
+ exit

作为一个健康的替代品,您可以在允许的提示列表中使用负正则表达式匹配,如下所示

if [[ ! $stdin =~ ^(y|Y|n|N)$ ]]

另一种只检查变量空字符串的有效方法

if [ "$stdin" = "" ]