在 Bash 中,如何读取文件并将每一行作为增量变量?

在 Bash 中,如何读取文件并将每一行作为增量变量?

我有一个如下文件:(list.txt)

127.0.0.1 us
127.0.0.2 uk
127.0.0.3 cn
127.0.0.4 fr
127.0.0.5 ru
127.0.0.6 bd
127.0.0.7 hk

我想制作一个脚本来向用户显示要选择的项目。

bash ping.sh
Which ip you want to test?

1) 127.0.0.1-us
2) 127.0.0.2-uk
3) 127.0.0.3-cn
4) 127.0.0.4-fr
5) 127.0.0.5-ru
6) 127.0.0.6-bd
7) 127.0.0.7-hk

Input: 6

ping -c 5 127.0.0.6

每当文件更改时,该列表也会更改。我该怎么做?

答案1

#!/bin/bash

PS3="Input: "

while read -r addr tld; do
  addrlist+=( "$addr" ) 
done < list.txt

echo "Which ip you want to test?"

select addr in "${addrlist[@]}"; do
  ping -c5 "$addr"
  break;
done

请注意,如果您的文件仅包含一个(地址)字段,则可以使用 bashmapfile内置函数(或其同义词readarray

mapfile -t addrlist < list.txt

无需显式循环即可填充数组。如果您想要原始问题中显示的精确带连字符列表,则可以执行以下操作

mapfile -t addrlist < list.txt

echo "Which ip you want to test?"

select addr in "${addrlist[@]// /-}"; do
  ping -c5 "${addr%%-*}"
  break;
done

但在我看来,代码开始变得丑陋。

答案2

#!/bin/bash

IFS=$'\n'
select choice in $(cat list.txt; echo exit)
do
    # echo "$REPLY : $choice"
    if [[ $choice != "exit" ]]
    then
        echo "your choice was: "$choice
        # Run your program here
    else
        exit
    fi
done

答案3

假设bash你指的是cli(终端)命令来完成这项工作。只有交际的部分由命令本身完成python(当然)由ping

所有内容都在一个小python脚本中:

#!/usr/bin/env python3
import subprocess
import sys

print("Which ip do you want to test?\n")
# create a numbered list of the lines
ips = list(enumerate(open(sys.argv[1]).read().splitlines()))
[print(str(i+1)+") "+ip) for i, ip in ips]
# run the command to ping
subprocess.call(["ping", "-c", "5", ips[int(input("\ninput: "))-1][1]])
  • 将脚本复制到一个空文件中,另存为ping_ip.py
  • 使用你的 as 参数运行它list.txt

    python3 /path/to/ping_ip.py /path/to/list.txt`
    

    在此处输入图片描述

笔记

参数“5”(ping 次数)位于以下行:

subprocess.call(["ping", "-c", "5", ips[int(input("\ninput: "))-1][1]])

但可以很好地改变为用作参数运行脚本时。如果这很方便,请提及。

答案4

这是我使用 AWK 大约 5 - 10 分钟后想出的东西。

$ select entry in $(awk '{printf "%s-%s ",$1,$2}'  ips.txt) ; do                                      
> ip_address=$(awk -F '-' '{print $1}' <<< "$entry" )                                                                 
> echo "You selected "  "$ip_address"
> done
1) 127.0.0.1-us
2) 127.0.0.2-uk
3) 127.0.0.3-cn
4) 127.0.0.4-fr
5) 127.0.0.5-ru
6) 127.0.0.6-bd
7) 127.0.0.7-hk
#? 2
You selected  127.0.0.2

您的问题中棘手的部分只是处理结构可以适当使用的文本文件行select,因为每行有两个条目。那么,为什么不把它们变成一个项目,然后进行后期处理以提取 IP 地址呢?这正是我在上面的代码中所做的。

请注意,第一个参数替换故意没有加引号 - 我们确实希望第一个命令扩展为用空格分隔的每个单独的项目,我们不希望它被视为一个字符串。

这种方法的好处在于它不受位置缺失的影响,例如,如果选项 #2uk缺失,我们仍然可以读取 127.0.0.2

相关内容