【问题标题】:For loop to produce a comma delimited string of appended valuesFor循环产生一个逗号分隔的附加值字符串
【发布时间】:2014-11-15 06:34:46
【问题描述】:

我有一个脚本:

    OUTPUT_DIR=/share/es-ops/Build_Farm_Reports/WorkSpace_Reports
    BASE=/export/ws
    TODAY=`date +"%m-%d-%y"`
    HOSTNAME=`hostname`
    WORKSPACES=( "bob_avail" "bob_used" "mel_avail" "mel_used" "sideshow-ws2_avail" "sideshow-ws2_used" )
    if ! [ -f $OUTPUT_DIR/$HOSTNAME.csv ] && [ $HOSTNAME == "sideshow" ]; then
    echo "$HOSTNAME" >  $OUTPUT_DIR/$HOSTNAME.csv # with a linebreak
    separator="," # defined empty for the first value
    for v in "${WORKSPACES[@]}"
    do
      echo -n "$separator$v" >> $OUTPUT_DIR/$HOSTNAME.csv # append, concatenated, the separator and the value to the file
      #separator="," # comma for the next values
    done
    echo >> $OUTPUT_DIR/$HOSTNAME.csv # add a linebreak (if you want it)
    fi
    WORKSPACES2=( "bob" "mel" "sideshow-ws2" )
    separator="" # defined empty for the first value
    for v in "${WORKSPACES2[@]}"
    do
        echo -n  "$separator`df -m $BASE/$v | awk '{if (NR!=1) {print $3","$2}}'`" >> $OUTPUT_DIR/$HOSTNAME.csv
        separator="," # comma for the next values
    done

产生这个:

sideshow
,bob_avail,bob_used,mel_avail,mel_used,sideshow-ws2_avail,sideshow-ws2_used
470400,1032124,661826,1032124,43443,1032108

但我希望第二个 for 循环将日期放在第一列中,如下所示:

09-20-14,470400,1032124,661826,1032124,43443,1032108

意义

$TODAY,<bob avail>,<bob used>,mel avail>,<mel used>,<sideshow-ws2 avail>,<sideshow-ws2 used>

所以整体输出如下所示:

sideshow
,bob_avail,bob_used,mel_avail,mel_used,sideshow-ws2_avail,sideshow-ws2_used
09-20-14,470400,1032124,661826,1032124,43443,1032108

如果这运行了一个 cron,那么我只需要检查主机名是否为 x 并且 .csv 文件是否存在:

sideshow
,bob_avail,bob_used,mel_avail,mel_used,sideshow-ws2_avail,sideshow-ws2_used
09-20-14,470400,1032124,661826,1032124,43443,1032108
09-20-15,470400,1032124,661826,1032124,43443,1032108

只需添加第二天的值。

【问题讨论】:

  • 您想要与-n 相同的技巧。循环WORKSPACES2,运行这两个命令,将它们都回显到文件中,然后继续。 (实际上只需要运行一次命令即可。使用{print $3","$2}。)
  • 由于某种原因,没有像第一个 for 循环那样在第一列中获得日期。我将输出粘贴到我的问题中。
  • 您不能像工作区一样循环遍历日期。您只需 echo -n 循环之前的文件即可。
  • 另外,顺便说一句,如果第一个只是为每个人提供 *_avail*_used 条目,则不需要两个 WORKSPACES 数组。只需在第一个循环中使用裸名称循环和 `echo -n "$separator${v}_avail,${v}_used"。

标签: arrays bash loops append


【解决方案1】:

首先,有一些简单的方法可以生成逗号分隔的列表。我通常使用的是paste -sd,,它要求值位于不同的行上。这很容易安排:

printf %s\\n "${WORKSPACES[@]}" | paste -sd,

但是,如果我们要通过实用程序传递printf,我们不妨将逗号与printf 一起放入并删除我们不想要的那个:

printf ,%s "{WORKSPACES[@]}" | cut -c2-

cutpaste 都将保证在它们的输出末尾有一个换行符。在这种情况下,这似乎是我们想要的,但如果不是,您可以使用"$(...)" 来消除换行符:

printf %s "$(printf ,%s "{WORKSPACES[@]}" | cut -c2-)"

额外的好处:使用 bash 单行生成 _avail_used 标签:

paste -d, <(printf %s_avail\\n "${WORKSPACES2[@]}") \
          <(printf %s_used\\n "${WORKSPACES2[@]}") | paste -sd,

现在,让我们考虑 df 调用。您正在调用df 六次,以便使用非常强大的工具 (awk) 提取各个字段,该工具可以为您完成所有工作。让我们这样做。首先,我们将告诉df 我们想要的所有文件系统,然后我们可以在获得它们时处理所有行,提取两个字段并用逗号输出它们。作为额外的奖励,我们也可以输出时间戳:

WORKSPACES2=( "bob" "mel" "sideshow-ws2" )
df -m "${WORKSPACES2[@]/#//export/ws/}" | awk '
    BEGIN  { print strftime("%m-%d-%y")}
    NR > 1 { printf ",%s,%s", $3, $2; }
    END    { printf "\n"}' >> "$OUTPUT_DIR/$HOSTNAME.csv"

以上假设 Gnu awk,它有一个 strftime 函数。对于其他 awk,您必须调用 shell:

df -m "${WORKSPACES2[@]/#//export/ws/}" | awk '
    BEGIN  { "date +%m-%d-%y" | getline date;
             printf "%s",date }
    NR > 1 { printf ",%s,%s", $3, $2; }
    END    { printf "\n"}' >> "$OUTPUT_DIR/$HOSTNAME.csv"

bash 表达式"${WORKSPACES2[@]/#//export/ws/}" 是一个迭代搜索和替换;也就是说,搜索和替换依次应用于数组的每个元素,为每个元素创建一个单独的“单词”。这种情况下的模式是#,在这里意味着“从行首开始的空模式”。替换在第二个/ 之后立即开始,我们不会(也不能)反斜杠转义下面的/,因为 bash 不期望替换中的尾随 /(并且反斜杠将被复制到如果我们把它们放进去,则替换)。我鼓励您尝试使用 echo 以及各种搜索和替换字符串,以便掌握它。

【讨论】:

  • 有没有办法像我上面显示的那样把日期放在第一列?
  • @BrianBills:是的,我刚刚添加了那个。
  • 如何将您的输出回显到 .csv 文件?当 cron 第二天开始时,我希望你的输出打印在上一条底线的正下方。
  • @BrianBills:你只是 &gt;&gt; file.csv 正常。这只是 bash。
  • @BrianBills:我对其进行了更改,以便awk 程序在末尾放置一个新行并添加附加的标准输出重定向。你应该能够弄清楚其余的,不是吗?
【解决方案2】:

在@rici 的帮助下,我能够让一切按我想要的方式工作:

    OUTPUT_DIR=/share/es-ops/Build_Farm_Reports/WorkSpace_Reports
    BASE=/export/ws
    TODAY=`date +"%m-%d-%y"`
    HOSTNAME=`hostname`
    WORKSPACES=( "bob_avail" "bob_used" "mel_avail" "mel_used" "sideshow-ws2_avail" "sideshow-ws2_used" )
    if ! [ -f $OUTPUT_DIR/$HOSTNAME.csv ] && [ $HOSTNAME == "sideshow" ]; then
    echo "$HOSTNAME" >  $OUTPUT_DIR/$HOSTNAME.csv # with a linebreak
    separator="," # defined empty for the first value
    for v in "${WORKSPACES[@]}"
    do
      echo -n "$separator$v" >> $OUTPUT_DIR/$HOSTNAME.csv # append, concatenated, the separator and the value to the file
      #separator="," # comma for the next values
    done
    echo >> $OUTPUT_DIR/$HOSTNAME.csv # add a linebreak (if you want it)
    WORKSPACES2=( "bob" "mel" "sideshow-ws2" )
    df -m "${WORKSPACES2[@]/#//export/ws/}" | awk '
        BEGIN  { "date +'%m-%d-%y'" | getline date;
                 printf "%s",date }
        NR > 1 { printf ",%s,%s", $3, $2; }
        END    { printf "\n"}' >> "$OUTPUT_DIR/$HOSTNAME.csv"
    elif [ $OUTPUT_DIR/$HOSTNAME.csv ] && [ $HOSTNAME == "sideshow" ]; then
    WORKSPACES2=( "bob" "mel" "sideshow-ws2" )
    df -m "${WORKSPACES2[@]/#//export/ws/}" | awk '
        BEGIN  { "date +'%m-%d-%y'" | getline date;
                 printf "%s",date }
        NR > 1 { printf ",%s,%s", $3, $2; }
        END    { printf "\n"}' >> "$OUTPUT_DIR/$HOSTNAME.csv"
    else
    :
    fi

在第一遍产生输出:

    sideshow
    ,bob_avail,bob_used,mel_avail,mel_used,sideshow-ws2_avail,sideshow-ws2_used
    09-20-14,470400,1032124,661826,1032124,43443,1032108

第二遍:

    sideshow
    ,bob_avail,bob_used,mel_avail,mel_used,sideshow-ws2_avail,sideshow-ws2_used
    09-20-14,470400,1032124,661826,1032124,43443,1032108
    09-20-14,470400,1032124,661826,1032124,43443,1032108

第三关:

    sideshow
    ,bob_avail,bob_used,mel_avail,mel_used,sideshow-ws2_avail,sideshow-ws2_used
    09-20-14,470400,1032124,661826,1032124,43443,1032108
    09-20-14,470400,1032124,661826,1032124,43443,1032108
    09-20-14,470400,1032124,661826,1032124,43443,1032108

这样当我每天使用 cron 运行它时,日期就会改变。很棒的工作,感谢@rici。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-19
    • 2014-06-13
    • 1970-01-01
    • 1970-01-01
    • 2012-03-14
    相关资源
    最近更新 更多