【问题标题】:Loops in Shell Scripting [closed]Shell脚本中的循环[关闭]
【发布时间】:2009-04-23 04:22:32
【问题描述】:

我需要有关此 shell 脚本的帮助。

  1. 必须使用某种循环。
  2. 必须完全按照所示使用输入数据。
  3. 输出重定向应该在脚本中完成,而不是在命令行中。

这是我的输入文件: http://pastebin.com/m3f783597

以下是输出需要的内容: http://pastebin.com/m2c53b25a

这是我失败的尝试: http://pastebin.com/m2c60b41

失败的尝试输出: http://pastebin.com/m3460e78c

【问题讨论】:

    标签: bash shell unix


    【解决方案1】:

    这里是帮助。在查看下面的解决方案之前,请尽量遵循这些。从长远来看,这将对您有更多帮助,从短期来看,您的教育工作者肯定会尽可能轻松地看到这一点。

    如果他发现你抄袭了代码,那可能意味着瞬间失败。

    您所说的“失败的尝试”在这里。第一次尝试其实还不错。

    echo -e "Name\t\t On-Call\t\t Phone"
    for daycount in 2 1 4 5 7 6 3
    do
        for namecount in 3 2 6 1 7 4 5
        do
            day=`head -n $daycount p2input2|tail -n 1|cut -f 2 -d " "`
            name=`head -n $namecount p2input1|tail -n 1|cut -f 1 -d " "`
            phone=`head -n $namecount p2input1|tail -n 1|cut -f 2 -d " "`
            echo -e "$name\c"
            echo -e "\t\t$day\c"
            echo -e "\t\t$phone"
            continue
        done
    done
    

    以下是提示:

    • 您有两个循环,一个在另一个内部,每个循环出现 7 次。这意味着 49 行而不是 7 行输出。您希望每天处理并查找当天的姓名和电话(实际上是当天的姓名和电话)。
    • 硬编码行号并不适合(尽管我承认它是偷偷摸摸的)——如果数据的顺序发生变化怎么办?最好根据值进行搜索。
    • 制表符使事情变得混乱,使用空格代替,因为那时输出不依赖于终端设置,您无需担心未对齐的制表符。

    为了完整起见,这里是两个输入文件和预期的输出:

    p2input1                  p2input2
    ========                  ========
    Dave 734.838.9801         Bob Tuesday
    Bob 313.123.4567          Carol Monday
    Carol 248.344.5576        Ted Sunday
    Mary 313.449.1390         Alice Wednesday
    Ted 248.496.2204          Dave Thursday
    Alice 616.556.4458        Mary Saturday
    Frank 634.296.3357        Frank Friday
    
    Expected output
    ===============
    Name            On-Call         Phone
    
    carol           monday          248.344.5576
    bob             tuesday         313.123.4567
    alice           wednesday       616.556.4458
    dave            thursday        734.838.9801
    frank           friday          634.296.3357
    mary            saturday        313.449.1390
    ted             sunday          248.496.2204
    

    说了这么多,假设您已经离开至少两个小时来尝试运行您的版本,这是我的:

     1 #!/bin/bash
     2 spc20="                    "
     3 echo "Name            On-Call         Phone"
     4 echo
     5 for day in monday tuesday wednesday thursday friday saturday sunday
     6 do
     7     name=`grep -i " ${day}$" p2input2 | awk '{print $1}'`
     8     name=`echo ${name} | tr '[A-Z]' '[a-z]'`
     9     bigname=`echo "${name}${spc20}" | cut -c1-15`
    10
    11     bigday=`echo "${day}${spc20}" | cut -c1-15`
    12
    13     phone=`grep -i "^${name} " p2input1 | awk '{print $2}'`
    14
    15     echo "${bigname} ${bigday} ${phone}"
    16 done
    

    下面的描述应该会有所帮助:

    • 第 1 行选择正确的 shell,并不总是必要的。
    • 第 2 行为我们提供了足够的空间来简化格式化。
    • 第 3-4 行给出了标题和空白行。
    • 第 5-6 行在一天中循环,一次一个。
    • 第 7 行给了我们一天的名称。 'grep -i " ${day}$"'pinput2 的行尾搜索给定的日期(无论大小写),而 awk 语句为您提供字段 1(名称)。
    • 第 8 行只是将名称全部小写。
    • 第 9 行通过添加 50 个空格然后在末尾截去除 15 之外的所有空格来创建大小合适的输出字符串。
    • 第 11 行当天也是如此。
    • 第 13 行与第 7 行非常相似,不同之处在于它搜索pinput1,在行的开始处查找姓名并将电话号码作为第二返回字段。
    • 第 15 行仅输出单个项目。
    • 第 16 行结束循环。

    所以你有它,足够的提示(希望)修复你自己的代码,以及一个关于专业人士如何做的示例:-)。

    阅读使用的工具是明智的,greptrcutawk

    【讨论】:

      【解决方案2】:

      我猜这是家庭作业?

      阅读排序和粘贴命令:man sortman paste

      【讨论】:

        【解决方案3】:

        Pax 给出了一个很好的答案,但此代码调用的进程更少(11 与最少 56 = 7 * 8)。它使用一个辅助数据文件来给出星期几和它们的序列号。

        cat <<! >p2input3
        1 Monday
        2 Tuesday
        3 Wednesday
        4 Thursday
        5 Friday
        6 Saturday
        7 Sunday
        !
        
        sort +1 p2input3 > p2.days
        sort +1 p2input2 > p2.call
        join -1 2 -2 2 p2.days p2.call | sort +2 > p2.duty
        sort +0 p2input1 > p2.body
        join -1 3 -2 1 p2.duty p2.body | sort +2n | tr '[A-Z]' '[a-z]' |
        awk 'BEGIN { printf("%-14s %-14s %s\n", "Name", "On-Call", "Phone");
                     printf "\n"; }
                   { printf("%-14s %-14s %s\n", $1, $2, $4);}'
        rm -f p2input3 p2.days p2.call p2.duty p2.body
        

        join 命令功能强大,但要求两个文件中的数据在连接键上按排序顺序排列。 cat 命令给出日期列表和日期编号。按日期名称的字母顺序列出的第一个排序位置。第二种也是按日期名称的字母顺序排列值班人员的姓名。然后第一个连接将这两个文件组合在日期名称上,然后根据用户名进行排序,产生输出:

        Wednesday 3 Alice
        Tuesday 2 Bob
        Monday 1 Carol
        Thursday 4 Dave
        Friday 5 Frank
        Saturday 6 Mary
        Sunday 7 Ted
        

        最后一个排序将姓名和电话号码按姓名字母顺序排列。然后第二个连接将姓名 + 电话号码列表与姓名 + 职责列表相结合,产生 4 列输出。这是通过tr 运行以使数据全部小写,然后使用awk 格式化,这很好地展示了它的强大和简单性(你可以使用Perl 或Python,但坦率地说,这会更麻烦)。

        Perl 有一句座右铭:TMTOWTDI “有不止一种方法可以做到”。

        这通常也适用于 shell 脚本。


        我想我的代码没有使用循环......哦,亲爱的。将最初的 cat 命令替换为:

         for day in "1 Monday" "2 Tuesday" "3 Wednesday" "4 Thursday" \
                    "5 Friday" "6 Saturday" "7 Sunday"
         do echo $day
         done > p2input3
        

        这现在符合规则的文字。

        【讨论】:

          【解决方案4】:

          试试这个:

          sort file1.txt > file1sort.txt
          sort file2.txt > file2sort.txt
          join file2sort.txt file1sort.txt | column -t > result.txt
          rm file1sort.txt file2sort.txt
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2017-11-13
            • 2018-01-08
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2022-05-17
            相关资源
            最近更新 更多