如何使用shell解析文本文件

时间:2015-11-09 09:04:08

标签: linux bash sh

我有一个带有示例数据的文本文件'builds.txt',如下所示。我只想知道MARX_BUILD号码,即12.我怎样才能实现它。 我尝试了grep MARX_BUILD builds.txt,它给出了MARX_BUILD = 12。

AM_BUILD_NO=1500
KJI_BUILD_NO=374
LINE_BUILD_NO=365
MARX_BUILD_NO=12

4 个答案:

答案 0 :(得分:8)

你已经是那里的一部分了,所以一个选项就是将你的输出输出到cut:

grep MARX_BUILD builds.txt | cut -d= -f2

这会分割=上的一行并打印第二个字段。

就个人而言,我会使用awk一次性完成整个事情:

awk -F= '/MARX_BUILD/ { print $2 }' builds.txt

这样做相同但只使用一个工具而不是两个。

答案 1 :(得分:3)

仅限

执行此操作有3种方法,无需外部二进制文件(例如或其他人。)

1。 Eval,(但是eval是邪恶的)

如果您信任该文件的来源,则可以来源

source builds.txt
echo $KJI_BUILD_NO
374

2。将整个文件读入关联数组

如果稍强一点,这种方法会更加安全。

declare -A AArray
while IFS== read var val ;do
    [[ "$var" =~ ^[A-Za-z_]*$ ]] && AArray[$var]=$val
  done <builds.txt
echo ${AArray[MARX_BUILD_NO]}
12

3。只有一个字段

与之前一样,此方法比eval更安全,如果您只需要在配置文件中访问一个字段,那么您可以:

ans=$(<builds.txt)
ans=${ans#*LINE_BUILD_NO=}
ans=${ans%%[${IFS}]*}
echo $ans
365

field=KJI_BUILD_NO
ans=$(<builds.txt);ans=${ans#*${field}=};ans=${ans%%[${IFS}]*};echo $ans
374

时间比较

我更喜欢避免 forks 以提高执行脚本的速度。

让我们展示一些差异(在我的主持人身上),速度有一点分类:

  1. 采购(但关心信任源文件)!

    time for ((i=1000;i--;));do . builds.txt ;done;echo $MARX_BUILD_NO
    0.044s 
    12
    
  2. 关联数组

    declare -A AArray
    time for ((i=1000;i--;)) ;do
        while IFS== read var val ;do
            [[ "$var" =~ ^[a-zA-Z0-9_]*$ ]] && AArray[$var]=$val
          done <builds.txt
      done ;echo ${AArray[MARX_BUILD_NO]}
    0.356s 
    12
    
  3. grep -Po

    time for ((i=1000;i--;));do ans=$(
        grep -Po '^MARX_BUILD_NO=\K\d*$' builds.txt);done;echo $ans
    1.406s 
    12
    
  4. sed

    time for ((i=1000;i--;));do ans=$(
        sed -ne 's/MARX_BUILD_NO=//p' builds.txt);done;echo $ans
    1.454s 
    12
    
  5. awk

    time for ((i=1000;i--;));do ans=$(
        awk -F= '/MARX_BUILD_NO/{print $2}' builds.txt);done;echo $ans
    2.089s 
    12
    
  6. grep | cut

    time for ((i=1000;i--;));do ans=$(
        grep MARX_BUILD_NO builds.txt | cut -d '=' -f2)
      done;echo $ans
    2.292s 
    12
    
  7. 显然,由于 fork pipe ,最后一种方法需要花费大量时间,因此必须为每个变量赋值运行两个新的独立进程。

答案 2 :(得分:1)

如果grep支持PCRE,您可以执行以下操作:

grep -Po '^MARX_BUILD_NO=\K\d*$' builds.txt

sed

sed -n 's/^MARX_BUILD_NO=\([0-9]*\)$/\1/p' builds.txt

答案 3 :(得分:1)

如果你的grep不支持PCRE,你可以

grep MARX_BUILD_NO builds.txt | cut -d '=' -f2