是否可以将不同的内容回显到在 bash 循环范围内创建的不同文件?

Is it possible to echo different contents to different files created in a bash range for loop?

我正在尝试创建一个名为 create.ip.list.txt.sh

的脚本

当运行我希望输出如下:

[root@ubuntu]$ head li*
==> list1.txt <==
192.168.1.100
192.168.1.101
192.168.1.102
192.168.1.103
192.168.1.104

==> list2.txt <==
192.168.1.105
192.168.1.106
192.168.1.107
192.168.1.108
192.168.1.109

==> list3.txt <==
192.168.1.110
192.168.1.111
192.168.1.112
192.168.1.113
192.168.1.114

这是我目前的脚本:

#!/bin/bash
i=1
for i in list{1..3}.txt; do
        echo -e -n "\b192.168.1.10"{0..4}"\n" > $i
        echo -e -n "\b192.168.1.10"{5..9}"\n" > $i
        echo -e -n "\b192.168.1.1"{10..14}"\n" > $i
done;

但是当我 运行 代码时,这是我得到的输出:

[root@ubuntu]$ head li*
==> list1.txt <==
192.168.1.110
192.168.1.111
192.168.1.112
192.168.1.113
192.168.1.114

==> list2.txt <==
192.168.1.110
192.168.1.111
192.168.1.112
192.168.1.113
192.168.1.114

==> list3.txt <==
192.168.1.110
192.168.1.111
192.168.1.112
192.168.1.113
192.168.1.114
[root@ubuntu]$

它循环并根据需要创建单独的文件,但它似乎将最后一个 echo 命令回显到所有文件。有谁知道我做错了什么或者你可以指出我正确的方向吗?提前致谢。

如果有人问过这个问题,我深表歉意,但我已经尝试四处寻找解决方案,但没有出现与我的情况完全相同的情况。通常,posts 有 运行ge 循环写入单个文件,在这里我想要从 运行ge 循环创建多个文件。也许我在搜索时没有使用正确的术语,但我们将不胜感激任何帮助。如果这个问题已经被问过,请不要惩罚我。如果有,请告诉我,我可以删除 post 或根据需要重新放置它。

此致,

一个谦逊的学生

  1. 它将向所有文件写入相同的内容,因为您不会根据您所在的文件更改在循环内写入的内容。它在每一行上独立且完整地展开花括号展开;这三个文件分别创建的唯一原因是第一个这样的扩展是 for...in 循环初始化子句的一部分。一旦您查看代码在卷曲扩展后的样子,它可能会更有意义:

     for i in list1.txt list2.txt list3.txt; do
        echo -e -n "\b192.168.1.10"0"\n" "\b192.168.1.10"2"\n" "\b192.168.1.10"3"\n" "\b192.168.1.10"4"\n" > $i
        echo -e -n "\b192.168.1.10"5"\n" "\b192.168.1.10"6"\n" "\b192.168.1.10"7"\n" "\b192.168.1.10"8"\n" "\b192.168.1.10"9"\n" > $i
        echo -e -n "\b192.168.1.1"10"\n" "\b192.168.1.1"11"\n" "\b192.168.1.1"12"\n" "\b192.168.1.11"13"\n" "\b192.168.1.1"14"\n" > $i
     done
    
  2. 您只能看到最后写入的内容,因为您使用的是 >,它会覆盖整个文件。如果你打算分别重定向每一行,你会想要使用 >>,它附加在文件的末尾而不删除已经存在的内容。

但是只使用几个嵌套的计数循环和一些数学运算,并将整个内部循环重定向到文件作为仍然可以使用 >:

的单个重定向会更简单
for i in {0..2}; do  # or for (( i=0; i<3; ++i )); do
  for j in {0..4}; do  # or for (( j=0; j<5; ++j )); do
    let b=100+i*5+j
    printf '\b192.168.1.%d\n' "$b"
  done >list$((i+1)).txt
done

我使用 printf 而不是 echo -e -n,因为 printf 比 bash 更简单并且可移植到更多的 shell。不过,我不确定您为什么要在 IP 地址文本文件的每一行的开头写一个退格键;如果你放弃你可以只使用 echo 192.168.1.$b.

回应您关于超过 255 的评论:如果您想对 IP 地址执行算术运算,我会考虑使用 shell 及其内置算术功能以外的其他东西。您友好的社区包管理器中可能有许多专用的 IP 操作工具可用,但您可以使用可能已经安装的工具,例如 Ruby:

ip=192.168.1.250
for i in {0..2}; do
  f=list$((i+1)).txt
  for j in {0..4}; do
    printf '\b%s\n' "$ip"
    ip=$(ruby -ripaddr -lpe '$_=IPAddr.new(IPAddr.new($_).to_i+1,2)' <<<$ip)
  done >"$f"
done

之后 list2.txt 看起来像这样:

192.168.1.255
192.168.2.0
192.168.2.1
192.168.2.2
192.168.2.3

如果使用 printf,则不需要任何循环。

此外,如果您想根据行数拆分内容,请使用 split 命令。

printf "192.168.10.1%02d\n" {0..14} | 
  split --lines=5 --suffix-length=1 --additional-suffix=.txt \
        --numeric-suffixes=1 - list