是否有可能将不同的内容回显到bash范围内创建的不同文件中进行循环?

时间:2018-10-30 16:05:26

标签: bash scripting range echo io-redirection

我正在尝试创建一个名为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命令回显到所有文件。有人知道我在做什么错吗,或者您可以为我指明正确的方向?预先感谢。

很抱歉,是否已经有人提出这个要求,但是我试图四处寻找解决方案,但没有弹出类似我的情况的信息。通常,帖子将范围循环写入单个文件,在这里我要从范围循环创建多个文件。也许我在搜索时没有使用适当的术语,但是任何帮助将不胜感激。如果已经问过这个问题,请不要惩罚我。如果有,请告诉我,如有需要,我可以将其删除或重新安置。

此致

一个谦虚的学生

2 个答案:

答案 0 :(得分:2)

  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

答案 1 :(得分:0)

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

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

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