在BASH脚本中搜索/查找文件中文本的最佳/优化方式

时间:2019-03-14 13:45:56

标签: bash command-line grep

我有一个包含数十万条记录的文件。所有这些记录都是唯一的,用逗号分隔的值。第一列可以认为是关键,第二列是感兴趣的值。

文件大小为8到10 MB。我必须不时在脚本中查找这些值。目前,我正在使用以下grep语句:

  

myvalue = $(grep $ myvar文件名| cut -d,-f2)

它可以正常工作,但是真正的问题是对同一文件的多次/顺序查找。我认为这不是一种非常优化的方法,因为在脚本运行期间我必须多次从同一文件中查找(超过100-200次),因此每次都要grep整个文件。我想要一些更好/优化的方法。

更新 需要特别注意的是它是顺序脚本,并且$ myvar中的所有值都是在运行时生成的,所以我不能拥有所有可用值并进行组合查找,因此每次迭代都必须是一个值查找

3 个答案:

答案 0 :(得分:2)

我要考虑的显而易见的事情是Type结果的局限性,这可以通过public class RequestOperation { public enum Type { //enum values and mappings } private String applicationUrl; private ArrayList<String> requestParams = new ArrayList<>(); public RequestOperation(Type operationType) { this.applicationUrl = composeUrl(operationType, requestParams); } public RequestOperation(Type operationType, String paramFirst) { this.requestParams.add(0, paramFirst); new RequestOperation(operationType); } public RequestOperation(Type operationType, String paramFirst, String paramSecond) { this.requestParams.add(0, paramSecond); new RequestOperation(operationType, paramFirst); } public RequestOperation(Type operationType, String paramFirst, String paramSecond, String paramThird) { this.requestParams.add(0, paramThird); new RequestOperation(operationType, paramFirst, paramSecond); } 开关来完成:

grep

答案 1 :(得分:2)

如果文件一次构造,然后一遍又一遍地引用而又没有在其间进行更改,则需要使用关联数组作为查找表。这可能会变得越来越丑陋。考虑使用perl。

但是,您问如何用bash进行操作。

$: eval "declare -A lookup=(
   $( sed -E 's/^([^,]+),([^,]+).*/  [\1]=\2/' filename )
   )" 

现在所有值都应在表lookup中。

关联数组使用字符串作为键而不是整数,因此这会将键和值设置为表中的对。

sed -E 's/^([^,]+),([^,]+).*/  [\1]=\2/'

采用逗号分隔文件的第一和第二字段,并将其重新格式化为bash语法的键/值分配,如下所示:

declare -A lookup=(
   [a]=1
   [b]=2
   [c]=3 # ... and so on
) 

eval将所有内容解析到当前环境中供您使用。

没有其他grep。只需使用"${lookup[$myvar]}"
如果您只是想为其分配可读性,请使用{p>而不是grep

myvalue="${lookup[$myvar]}"

我正在使用的本地示例

$: cat x
a,1,lijhgf
b,2,;lsaoidj
c,3,;l'skd

$: echo "declare -A lookup=(
   $( sed -E 's/^([^,]+),([^,]+).*/  [\1]=\2/' x )
   )"
   declare -A lookup=(
     [a]=1
     [b]=2
     [c]=3
   )

$: eval "declare -A lookup=(
   $( sed -E 's/^([^,]+),([^,]+),.*/  [\1]=\2/' x )
   )"

$: echo "${lookup[b]}"
   2

答案 2 :(得分:1)

首先,让我们看一下您的命令:

myvalue=$(grep $myvar filename | cut -d, -f2)

您使用加载的2个二进制文件(grepcut)来处理数据。您应该尝试将其减少为单个二进制文件。这已经很有帮助:

myvalue=$(awk -F, -v var="$myvar" '$0~var { print $2; exit}' filename)

这将更快:

  • 这是一个图书馆
  • 从找到条目开始停止读取文件

如果您需要根据第一列中的键进行多次查找,则可以在bash中执行以下操作:

 while IFS= read -r; do
    declare -A z+="( $REPLY )"
 done < <(awk -F, '{print "["$1"]="$0}' lookupfile)

 echo ${z[$key]}

基于How do I populate a bash associative array with command output?