【问题标题】:Easier way to compare variables比较变量的更简单方法
【发布时间】:2013-03-22 11:21:15
【问题描述】:

我需要将文件“tmpcsv2”中的一组变量与“uniq_id”中的变量进行比较,我将在下面详细说明文件。

tmpcsv2 -> 此文件由另一个脚本“script1”更新,并且每次运行“script1”都会更新(而不是附加)“tmpcsv2”中的新变量。没有。变量的个数可能是 1,并且可以达到 200。

eg:
2042344352
2470697747
2635527510
3667769962

uniq-id -> 这是一组固定的变量(大约 10 万个)

(Business Name,Job ID,Job Size)
biz,1000036446,225210640
biz,100006309,6710840
biz,1000069211,2084019000
biz,1000118720,34194040
biz,1000150241,212322636

我正在使用“for”循环+“if”来比较它们,如下所示,有没有更简单或更快(影响更小)的方法?当我运行它时,需要很长时间才能输出结果。打印命令仅供测试,稍后会删除!

****Part of a bigger script****
amt=0
mjc=0
for jbid in `cat tmpcsv2` #Pick ID for match & calculation
do
    printf "Checking ID $jbid\n" >> Acsv3.tmp
    for bsid in `cat uniq_id` #Matching jobs & size calulation
    do
        ckid=`echo $bsid | cut -d "," -f2` #ckid is the ID to check
        jbsiz=`echo $bsid | cut -d "," -f3` #size of the ID
        if [ $jbid == $ckid ] 
        then
            printf "Matched at $ckid\n" #Print on Match found
            printf "Valid -> $jbid\n" >> Bcsv3.tmp
            ((mjc++)) #Increment Matched Job Count
            amt=$((amt+jbsiz)) #Add size of matched jobs
            break
        else
            printf "No Match at $cksid\n" #No matches
        fi
    done
    printf "Check for ID $jbid done\n" >> Acsv3.tmp
    printf "Matched $mjc jobs with combined size of $amt\n" >> Acsv3.tmp
done
****End of Comparision****

【问题讨论】:

  • 您输入的确切格式是什么?请注意,除了输出之外,您实际上并没有在任何地方使用 jbid 变量,因此比较本身甚至不涉及该文件。
  • @ormaaj,我已经编辑了脚本以显示 'jbid' 的使用,我用它来比较变量。

标签: bash shell if-statement for-loop comparison


【解决方案1】:

shell 是处理这么多数据的错误工具,但它是可行的。这里最基本的错误是reading lines with for。通过在每次迭代中不重新打开文件,可以显着提高性能。

function main {
    # Variables used elsewhere should be initialized there, not localized here.
    typeset amt=0 mjc=0 jbid ckid jbsiz

    while IFS= read -r jbid; do
        printf 'Checking ID %s\n' "$jbid" >&3
        while IFS=, read -r _ ckid jbsiz _; do
            case $jbsiz in
                *[^[:digit:]]*|'')
                    # validation is important for subsequent arithmetic.
                    return 1
                    ;;
                "$ckid") # Assuming "cksid" was a typo. Replace if not.
                    printf 'Matched at %s\n' "$ckid"
                    printf 'Valid -> %s\n' "$jbid" >&4
                    (( mjc++, amt += jbsiz ))
                    break
                    ;;
                *)
                    printf 'No match at %s\n' "$ckid"
            esac
        done <uniqid
        {
            printf 'Check for ID %s done\n' "$jbid"
            printf 'Matched %s jobs with combined size of %s\n' "$mjc" "$amt"
        } >&3
    done <tmpcsv2 3>>Acsv3.tmp 4>>Bcsv3.tmp
}

最后,一个等效的 awk 脚本将大大优于这个 Bash 脚本,几乎任何其他语言也是如此。您还可以通过使用 mapfile 而不是读取循环从 Bash 中获得更多性能,但是使用 mapfile 回调来模拟这种嵌套的读取循环逻辑有点草率。

【讨论】:

  • 这是外壳吗?你能用类似的逻辑构建一个 awk 吗?
  • 这是 shell,使用了一些 bash/ksh 特定的语法。希望它接近你想要的。我可以做 awk,但其他人可能会比我做得更好......我通常需要稍微 RTFM。
【解决方案2】:

我想出了这个,不确定是否可以缩短,但它确实运行得更快!任何帮助将不胜感激!

************
while read -r line  #File read start
do
IFS=$","
val=$line
amt=0
mjc=0
cjc=0
for lsid in $val
do
    cksid=`echo $lsid | sed -e 's/*//g' -e 's/"//g'`
    printf "Checking for $cksid\n"
    ((cjc++)) #Count of jobs to check
    prsnt=`grep -w $cksid uniq_id`
    if [ $? -eq 0 ]
    then
        printf "Valid -> $cksid\n"
        jbsiz=`grep -w $prsnt | cut -d, -f2`
        (( mjc++, amt += jbsiz ))
        break
    else
        printf "No Data for $cksid\n"
    fi

done
done < tmpcsv2
***********

【讨论】:

  • 这个脚本我几乎尝到了胜利的滋味……但是,我使用了“grep”,这并没有让我感到悲伤! grep 使所有三个值看起来都一样! --> 448742, 3660'448742', 115'448742'464
  • 我对输入文件进行了一些更改,现在 grep 工作正常!谁能检查一下,让我知道这是否是一个比较好的方法?
猜你喜欢
  • 2011-07-08
  • 2013-01-29
  • 1970-01-01
  • 1970-01-01
  • 2013-10-09
  • 2016-01-21
  • 2021-02-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多