计算特殊字符分隔符的数量 bash shell 脚本性能改进
Counting number of delimiters of special character bash shell script Performance improvement
您好,我有一个脚本,它将计算文件中的记录数,并通过将总记录数除以 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
计算分隔符(不是总记录)一个文件
在一个包含 50,000 行的文件中,我注意到通过将 sed
、grep
和 wc
管道合并到单个 awk
进程中,增加了大约 10 倍:
awk -v RS='<strong>Delimiter</strong>' 'END{print NR -1}' input_file
在没有尾随换行符时处理 wc
如果计算 ^
(行首)的实例,您将获得真实的行数。使用 grep
:
grep -co "^" input_file
(值得庆幸的是,尽管 ^
是一个正则表达式,但它的性能与 wc
相当)
根据您提供的代码将这两个修改合并到一个简单的测试中:
#!/usr/bin/env bash
SOURCE=""
RS=$'6'
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=$'6' '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's it,用10行随机字符创建/tmp/testfile包括八进制6
,然后在测试文件上运行脚本文件)
echo $'#!/usr/bin/env bash\n\nSOURCE=""\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 $'6459ca4f23bafff1c8fc017864aa3930c4a7f2918b6753f00e5a9278375b\nb6a36fc074b0e415f960e7099651abf3696a6f6f70263973e17657267355\n1590f285e076797aa83b2ee537c7f99666990bb60419b8aa6bb5b6b67053\n89b938a56560a54f2826250a2c026c3203025293312292556ef79fbb52c2\n90426bb6b942408a22f912268ffc78f08c62798b0c05a754396245be2ea5\n0ef03170413f90e6e06b1b2515c466bf0a1bb6ee28b78ccce70432e6b653\n51229e7ab228b4518404360b31a63673261e3242985bf24e59bc6576999a\n99646b08640e63fae788ea6a177760e94f89af8b571e6e1b53e63326c36e\n906ae12895f689885e6e736f942080f267a275132a348ec1e837b99efe94\n2895e9166f506f6c1b986a63444b42586bc1b39182630696be' > /tmp/testfile ; chmod +x /tmp/recordtest ; /tmp/./recordtest /tmp/testfile
产生这个结果:
$rs_count: 39
$Delimiter_per_record: 3
$total_record_count: 10
虽然有很多解决方案可以计算文件中的字符实例,但在尝试处理特殊字符(如八进制 6
[=29 时,有相当多的解决方案无法解决=]
awk
似乎可以可靠且快速地处理它。
您好,我有一个脚本,它将计算文件中的记录数,并通过将总记录数除以 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
计算分隔符(不是总记录)一个文件
在一个包含 50,000 行的文件中,我注意到通过将 sed
、grep
和 wc
管道合并到单个 awk
进程中,增加了大约 10 倍:
awk -v RS='<strong>Delimiter</strong>' 'END{print NR -1}' input_file
在没有尾随换行符时处理 wc
如果计算 ^
(行首)的实例,您将获得真实的行数。使用 grep
:
grep -co "^" input_file
(值得庆幸的是,尽管 ^
是一个正则表达式,但它的性能与 wc
相当)
根据您提供的代码将这两个修改合并到一个简单的测试中:
#!/usr/bin/env bash
SOURCE=""
RS=$'6'
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=$'6' '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's it,用10行随机字符创建/tmp/testfile包括八进制6
,然后在测试文件上运行脚本文件)
echo $'#!/usr/bin/env bash\n\nSOURCE=""\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 $'6459ca4f23bafff1c8fc017864aa3930c4a7f2918b6753f00e5a9278375b\nb6a36fc074b0e415f960e7099651abf3696a6f6f70263973e17657267355\n1590f285e076797aa83b2ee537c7f99666990bb60419b8aa6bb5b6b67053\n89b938a56560a54f2826250a2c026c3203025293312292556ef79fbb52c2\n90426bb6b942408a22f912268ffc78f08c62798b0c05a754396245be2ea5\n0ef03170413f90e6e06b1b2515c466bf0a1bb6ee28b78ccce70432e6b653\n51229e7ab228b4518404360b31a63673261e3242985bf24e59bc6576999a\n99646b08640e63fae788ea6a177760e94f89af8b571e6e1b53e63326c36e\n906ae12895f689885e6e736f942080f267a275132a348ec1e837b99efe94\n2895e9166f506f6c1b986a63444b42586bc1b39182630696be' > /tmp/testfile ; chmod +x /tmp/recordtest ; /tmp/./recordtest /tmp/testfile
产生这个结果:
$rs_count: 39
$Delimiter_per_record: 3
$total_record_count: 10
虽然有很多解决方案可以计算文件中的字符实例,但在尝试处理特殊字符(如八进制 6
[=29 时,有相当多的解决方案无法解决=]
awk
似乎可以可靠且快速地处理它。