计算特殊字符bash shell脚本的分隔符数量性能改进

问题描述 投票:1回答:1

嗨我有一个脚本,它将计算文件中的记录数,并通过将总记录数除以rs_count来查找每个记录的预期分隔符。它工作正常,但在大型记录上有点慢。我想知道是否有办法提高性能。 RS是一个特殊字符八进制\ 246。我正在使用bash shell脚本。

一些额外的信息:

一条线是一条记录。该文件将始终具有相同数量的分隔符。该脚本的目的是检查文件是否具有预期的字段数。在计算完之后,脚本就会回复它。

for file in $SOURCE; do
        echo "executing File -"$file
        if (( $total_record_count != 0 ));then
        filename=$(basename "$file")
        total_record_count=$(wc -l < $file)
        rs_count=$(sed -n 'l' $file | grep -o $RS | wc -l)
        Delimiter_per_record=$((rs_count/total_record_count))
        fi
done
bash shell unix delimiter
1个回答
1
投票

计算文件中的分隔符(不是总记录)

在一个包含50,000行的文件中,我注意到将sedgrepwc管道合并到单个awk流程中大约增加了10倍:

  • awk -v RS='Delimiter' 'END{print NR -1}' input_file

当没有拖尾线时,处理wc

如果计算^(行首)的实例,您将获得真正的行数。使用grep

  • grep -co "^" input_file

(值得庆幸的是,即使^是一个正则表达式,这个表现与wc相当)


根据您提供的代码将这两个修改合并到一个简单的测试中:

#!/usr/bin/env bash

SOURCE="$1"
RS=$'\246'

for file in $SOURCE; do
    echo "executing File -"$file
    if [[ $total_record_count != 0 ]];then
        filename=$(basename "$file")
        total_record_count=$(grep -oc "^" $file)
        rs_count="$(awk -v RS=$'\246' 'END{print NR -1}' $file)"
        Delimiter_per_record=$((rs_count/total_record_count))
    fi
done

echo -e "\$rs_count:\t${rs_count}\n\$Delimiter_per_record:\t${Delimiter_per_record}\n\$total_record_count:\t${total_record_count}" | column -t

在我的macbook上的50,000行文件上运行:

time ./recordtest.sh /tmp/randshort

executing File -/tmp/randshort
$rs_count:              186885
$Delimiter_per_record:  3
$total_record_count:    50000

real    0m0.064s
user    0m0.038s
sys     0m0.012s

单元测试单线

(创建/tmp/recordtest,chmod + x,创建/ tmp / testfile,包含10行随机字符,包括octal \246,然后在testfile上运行脚本文件)

echo $'#!/usr/bin/env bash\n\nSOURCE="$1"\nRS=$\'\\246\'\n\nfor file in $SOURCE; do\n    echo "executing File -"$file\n    if [[ $total_record_count != 0 ]];then\n        filename=$(basename "$file")\n        total_record_count=$(grep -oc "^" $file)\n        rs_count="$(awk -v RS=$\'\\246\' \'END{print NR -1}\' $file)"\n        Delimiter_per_record=$((rs_count/total_record_count))\n    fi\ndone\n\necho -e "\\$rs_count:\\t${rs_count}\\n\\$Delimiter_per_record:\\t${Delimiter_per_record}\\n\\$total_record_count:\\t${total_record_count}" | column -t' > /tmp/recordtest ; echo $'\246459ca4f23bafff1c8fc017864aa3930c4a7f2918b\246753f00e5a9278375b\nb\246a3\246fc074b0e415f960e7099651abf369\246a6f\246f70263973e176572\2467355\n1590f285e076797aa83b2ee537c7f99\24666990bb60419b8aa\246bb5b6b\2467053\n89b938a5\246560a54f2826250a2c026c320302529331229255\246ef79fbb52c2\n9042\246bb\246b942408a22f912268ffc78f08c\2462798b0c05a75439\246245be2ea5\n0ef03170413f90e\246e0\246b1b2515c4\2466bf0a1bb\246ee28b78ccce70432e6b\24653\n51229e7ab228b4518404360b31a\2463673261e3242985bf24e59bc657\246999a\n9964\246b08\24640e63fae788ea\246a1777\2460e94f89af8b571e\246e1b53e6332\246c3\246e\n90\246ae12895f\24689885e\246e736f942080f267a275132a348ec1e837b99efe94\n2895e91\246\246f506f\246c1b986a63444b4258\246bc1b39182\24630\24696be' > /tmp/testfile ; chmod +x /tmp/recordtest ; /tmp/./recordtest /tmp/testfile

产生这个结果:

$rs_count:              39
$Delimiter_per_record:  3
$total_record_count:    10

虽然有许多解决方案可以计算文件中的字符实例,但是在尝试处理像octal \246这样的特殊字符时会有一些解决方案失败。

awk似乎可靠而迅速地处理它。

© www.soinside.com 2019 - 2024. All rights reserved.