【问题标题】:bash script read text file line by line and comparebash脚本逐行读取文本文件并进行比较
【发布时间】:2016-04-19 16:14:33
【问题描述】:

我有一个格式为:

的文本文件
1292177423,20160206
1292177450,20160326
1292177503,20160204
1234263435,20160130
1234263464,20160219
1234263557,20160218
1234263564,20160321
1234263569,20160219
1292177912,20160314
abcde*****,yyyymmdd

=====

我想比较 yyyymmdd 和 20160115。如果> 20160115我想把这一行放到2个新文件中(1个只有数字abcde*****,1个有相同的旧文件号,yyyymmdd)

我可以使用 bash 脚本或 perl 脚本吗,因为这些文件的大小非常大?以及如何使用 bash 脚本来做到这一点?谢谢

【问题讨论】:

  • 这是一个是或否的问题;所以我会说这个答案是“是的”。请记住,Bash 脚本可以处理比大多数人想象的要大得多的文件。
  • 答案是yes。如果您确实需要帮助这样做,那么您应该尝试并在(如果)遇到困难时寻求帮助。
  • 是的,,,其实我想问问怎么做。

标签: bash shell


【解决方案1】:

答案是肯定的。与其尝试将整个文件读入脚本中的某种存储形式,只需 read 一次一行,并与每行中的 date 部分进行必要的比较,然后输出日期(用于重定向到第二个文件)。例如,您可以使用简单灵活的脚本,将 compare date 作为其第一个参数,然后从作为第二个参数给出的文件名中读取(或从 stdin默认)。例如

#!/bin/bash

[ -z $1 ] && {  ## validate compare date term provided
    printf "error: insufficient input, usage: %s cmpdate [file (stdin)]\n" \
    "${0##*/}"
    exit 1
}

cmpdt="${1:-20160401}"      ## compare date (default 20160401)
fname="${2:-/dev/stdin}"    ## filename (default stdin)

while IFS=$',\n' read -r num dt; do     ## read num, dt from each line
    [ "$dt" -ge "$cmpdt" ] && echo "$dt"    ## compare date/output
done <"$fname"

示例使用/输入/输出文件

使用您的比较日期20160401,以及存储在dat 目录中的输入文件为ndate.csv:

$ cat dat/ndate.csv
1292177423,20160206
1292177450,20160326
1292177503,20160204
1234263435,20160130
1234263464,20160219
1234263557,20160218
1234263564,20160321
1234263569,20160219
1292177912,20160314
1292177423,20160319
1292177450,20160326
1292177503,20160329
1234263435,20160401
1234263464,20160402
1234263557,20160405
1234263564,20160410
1234263569,20160418
1292177912,20160419

您可以使用上述脚本检查哪个日期大于或等于20160401,然后将匹配的日期转储到stdout:

$ bash cmpdates.sh 20160401 <dat/ndate.csv
20160401
20160402
20160405
20160410
20160418
20160419

当您对一切正常工作感到满意时,只需将输出重定向到一个新文件,例如dat/ndatenew.txt

$ bash cmpdates.sh 20160401 <dat/ndate.csv >dat/ndatenew.txt

$ cat dat/ndatenew.txt
20160401
20160402
20160405
20160410
20160418
20160419

要以xxxxxyyyyy 格式输出数据,您只需更改回显的信息,例如:

while IFS=$',\n' read -r num dt; do     ## read num, dt from each line
    [ "$dt" -ge "$cmpdt" ] && echo "${num:0:5}${dt:0:4}"    ## compare date/output
done <"$fname"

这会导致:

$ bash cmpdates.sh 20160401 <dat/ndate.csv
123422016
123422016
123422016
123422016
123422016
129212016

全部查看,如果您有任何问题,或者我误解了您在 file2 中想要的信息,请告诉我。

【讨论】:

  • Sr 因为让您理解错误,我的意思是 xxxxxyyyyy 是数字(而 y 不是年份).. 我只是更新.. 第一个捕获大于 20160401 的日期/时间的脚本工作正常。但是 file2 的输出是错误的 :)
  • 如果我现在明白了,你想要[ "$dt" -ge "$cmpdt" ] &amp;&amp; echo "$num"。试一试,它是日期之前的数字。
【解决方案2】:

awk 来救援!

文件大小无关紧要。

awk -F, '$2>20160115{print $1 > "file1"; print > "file2"}' file   

其中 file1 将只有第一个字段,而 file2 是满足条件的记录子集

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-18
    • 1970-01-01
    相关资源
    最近更新 更多