For循环生成逗号分隔的附加值字符串

时间:2014-09-21 00:44:53

标签: arrays bash loops append

我有一个脚本:

    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

只需添加第二天的值。

2 个答案:

答案 0 :(得分: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 one-liner生成_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功能。对于其他awks,您必须调用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/}"是一个迭代搜索和替换;也就是说,搜索和替换依次应用于数组的每个元素,创建一个单独的&#34;字&#34;对于每个元素。在这种情况下的模式是#,这里的意思是&#34;从行的开头开始的空模式&#34;。替换在第二个/之后立即开始,我们不会(并且不得)反斜杠 - 转义以下/,因为bash不会期望替换为/ (如果我们将反斜杠放入,则反斜杠将被复制到替换中)。我鼓励您尝试echo以及各种搜索和替换字符串,以便掌握它。

答案 1 :(得分:0)

在@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。