【问题标题】:How can I loop over comma-separated lists *inside* each line of a file?如何遍历文件的每一行 *inside* 的逗号分隔列表?
【发布时间】:2018-09-20 14:58:23
【问题描述】:

需要在 bash-script 中编写一些状态检查器:

有这样的字符串文件:

domain.com; 111.111.111.111,222.222.222.222; /link/to/somefile.js,/link/to/somefile2.js
domain2.com; 122.122.111.111,211.211.222.222; /link/to/somefile2.js,/link/to/somefile3.js

总共需要执行这样的命令:

curl -s -I -H 'Host: domain.com' http://111.111.111.111/link/to/somefile.js
curl -s -I -H 'Host: domain.com' http://222.222.222.222/link/to/somefile.js

curl -s -I -H 'Host: domain.com' http://111.111.111.111/link/to/somefile2.js
curl -s -I -H 'Host: domain.com' http://222.222.222.222/link/to/somefile2.js

curl -s -I -H 'Host: domain2.com' http://122.122.111.111/link/to/somefile2.js
curl -s -I -H 'Host: domain2.com' http://211.211.222.222/link/to/somefile2.js

curl -s -I -H 'Host: domain2.com' http://122.122.111.111/link/to/somefile3.js
curl -s -I -H 'Host: domain2.com' http://211.211.222.222/link/to/somefile3.js

问题是:

  1. 我需要使用什么工具才能得到这样的结果?
  2. 也许 xargs 带有一些参数/标志可以做到这一点,或者 gnu parallel
  3. 能否请您举例说明?

我可以分隔行并将结果设置为不同的变量,这根本不是问题:

domain=$(cut -d';' -f1 file| xargs -I N -d "," echo curl -H) \'N\'
ip=$(cut -d';' -f2 file| xargs -I N -d "," echo curl -H) \'N\'
and else

但其他问题:): 在将字符串分隔和分隔为变量之后,如何在这种情况下使用不同的变量执行 curl - 不同变量的参数数量会不同?

得到 Barmar 的答案根本不包括任务问题,因为它有两个以上的列表。问题不在于对 bash 的无知,而是我可以解决问题的方式

【问题讨论】:

  • 空格只能与分号连接是否准确?
  • 您可以在设置IFS 之后使用while read 循环,以便它在; 和空格上拆分。然后在空间上拆分 IP 和路径名部分,并为该部分使用嵌套循环。
  • StackOverflow 不是免费的编码服务。 SO希望您try to solve your own problem first。请更新您的问题以在minimal reproducible example 中显示您已经尝试过的内容。如需更多信息,请参阅How to Ask,并拨打tour :)
  • BashFAQ #1 是一个很好的起点。
  • 我相信这个问题可以分解为三个不同的技术挑战: 逐行迭代文件(将每一列读入不同的变量);将分隔符上的字符串拆分为数组;并以同步的方式迭代不同的数组(您将 IP 和文件字段拆分为的数组)。我们已经回答了有关如何做所有这些事情的问题。如果您在其他地方遇到困难,请edit 提出问题,以说明您是如何尝试应用这些答案的,以及您仍然遇到的问题。

标签: bash


【解决方案1】:
#!/usr/bin/env bash
#              ^^^^- IMPORTANT: not /bin/sh

# print command instead of running it, so people can test their answers without real URLs
log_command() { printf '%q ' "$@"; printf '\n'; }

while IFS='; ' read -r domain addrs_str files_str; do
  IFS=, read -a addrs <<<"$addrs_str"
  IFS=, read -a files <<<"$files_str"
  for file in "${files[@]}"; do
    for addr in "${addrs[@]}"; do
      log_command curl -s -I -H "Host: $domain" "http://$addr/$file"
    done
  done
done

...作为输出发出(如果删除了log_command 前缀,它将作为命令列表运行):

curl -s -I -H Host:\ domain.com http://111.111.111.111//link/to/somefile.js 
curl -s -I -H Host:\ domain.com http://222.222.222.222//link/to/somefile.js 
curl -s -I -H Host:\ domain.com http://111.111.111.111//link/to/somefile2.js 
curl -s -I -H Host:\ domain.com http://222.222.222.222//link/to/somefile2.js 
curl -s -I -H Host:\ domain2.com http://122.122.111.111//link/to/somefile2.js 
curl -s -I -H Host:\ domain2.com http://211.211.222.222//link/to/somefile2.js 
curl -s -I -H Host:\ domain2.com http://122.122.111.111//link/to/somefile3.js 
curl -s -I -H Host:\ domain2.com http://211.211.222.222//link/to/somefile3.js 

...正如您在https://ideone.com/dTC8q8 看到的那样


现在这是如何工作的?

【讨论】:

    【解决方案2】:

    使用 GNU Parallel,它看起来像这样

    doit() {
      domain="$1"
      ips="$2"
      paths="$3"
      parallel --dry-run -d ',' -q curl -s -I -H Host:\ "$domain" http://{1}/{2} ::: "$ips" ::: "$paths"
    }
    export -f doit
    parallel --colsep ';' doit :::: input.file
    

    当您确信 --dry-run 有效时删除它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-01-13
      • 1970-01-01
      • 2012-06-23
      • 1970-01-01
      • 2021-02-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多