微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

我想逐行读取文件并仅存储一些值

如何解决我想逐行读取文件并仅存储一些值

我有一个文件,其中以下内容重复n次

>QDN;6135785008
-------------------------------------------------------------------------------
DN:;;;;;5785008;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
TYPE:;SINGLE;PARTY;LINE
SNPA:;613;;;SIG:;DT;;;;LNATTIDX:;N/A;;;;;;;;;;;;;
LINE;EQUIPMENT;NUMBER:;;;;;BSAC;;39;0;00;01;;;
LINE;CLASS;CODE:;;IBN;;;
IBN;TYPE:;STATION
CUSTGRP:;;;;;;;;BSA_POS;;;;;SUBGRP:;0;;NCOS:;1
CARDCODE:;;V5LOOP;;;;GND:;N;;PADGRP:;NPDGP;;BNV:;NL;MNO:;N
PM;NODE;NUMBER;;;;;:;;;;80
PM;TERMINAL;NUMBER;:;;;;2
OPTIONS:
CWT;DGT;DDN;NOAMA;
;
-------------------------------------------------------------------------------
>QDN;6160160260
-------------------------------------------------------------------------------
DN:;;;;;0160260;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
TYPE:;SINGLE;PARTY;LINE
SNPA:;616;;;SIG:;DT;;;;LNATTIDX:;N/A;;;;;;;;;;;;;
LINE;EQUIPMENT;NUMBER:;;;;;BSAC;;39;0;00;03;;;
LINE;CLASS;CODE:;;IBN;;;
IBN;TYPE:;STATION
CUSTGRP:;;;;;;;;BSA_POS;;;;;SUBGRP:;0;;NCOS:;15
CARDCODE:;;V5LOOP;;;;GND:;N;;PADGRP:;NPDGP;;BNV:;NL;MNO:;N
PM;NODE;NUMBER;;;;;:;;;;80
PM;TERMINAL;NUMBER;:;;;;4
OPTIONS:
CWT;3WC;DGT;DDN;NOAMA;
;
----

我想读取所有行并将一些值存储到4个变量中。例如; var number(用“ QDN”表示的行的第二列),var类型(以PARTY开头的行),var snpa和var选项(在发生OPTIONS之后,它存储下一行的值)。输出可能是用分号分隔的文本文件(例如:var1; var2; var3; var4)。这部分起作用。我有以下代码,但无法将所有这些变量汇总在一起。我尝试在第一个循环中创建另一个while循环,以验证循环的“最后一次”检查(分隔信息块的分号),但是它也不起作用。

while IFS= read -r line || [[ -n "$line" ]]; read -r secondline; do
if [[ "$line" =~ ^'>QDN' ]]; then
    number=$(echo "$line" | awk -F ';' 'NF {print $2;}')                
elif [[ "$line" =~ ^'TYPE' ]]; then
    type=$(echo "$line" | awk -F ';' 'NF {print $2" "$3" "$4;}')    
elif [[ "$line" =~ ^'SNPA' ]]; then
    snpa=$(echo "$line" | awk -F ';' 'NF {print $2;}')  
elif [[ "$line" =~ ^'OPTIONS' ]]; then
    options=$(echo "${secondline}") 
fi  
echo $number";"$type";"$snpa";"$options         
done < "file.txt

上面代码输出有些混乱:

;613;CWT;3WC;DGT;DDN;NOAMA;SACB;ACT;I976;$;$;N;
;613;CWT;3WC;DGT;DDN;NOAMA;SACB;ACT;I976;$;$;N;
;613;CWT;DGT;DDN;NOAMA;
;613;CWT;DGT;DDN;NOAMA;
;613;CWT;DGT;DDN;NOAMA;
;613;CWT;DGT;DDN;NOAMA;
;616;CWT;DGT;DDN;NOAMA;
;616;CWT;DGT;DDN;NOAMA;
;616;CWT;DGT;DDN;NOAMA;
;616;CWT;DGT;DDN;NOAMA;
;616;DGT;ARTY LINE
;616;DGT;ARTY LINE
;616;DGT;ARTY LINE    

你们中的任何人都可以帮忙吗?

解决方法

重复的Awk类似小片段通常表明您应该改用Awk重写整个脚本。

以下内容假定OPTIONS总是排在其他字段之后。消除此限制并不难,但有了这一限制,代码非常简单。

awk -F ';' 'BEGIN { OFS=";" }
   /^>QDN/ { number = $2 }
   /^TYPE/ { type = $2 " " $3 " " $4 }
   /^SNPA/ { snpa = $2 }
   /^OPTIONS/ { options = 1; next }
   options { print number,type,snpa,$0;
      number = type = snpa = options = "" }' file.txt

您可能应该单独从文件中删除DOS回车,但是如果您还需要处理损坏的文件,则可以在顶部轻松添加NF { sub(/\r/,"") }

演示:https://ideone.com/zP102J

,

如果您在行读取循环中调用awk,则很可能是您做错了。您应该考虑以纯awk或纯bash的方式进行。以下是普通的bash版本:

#!/bin/bash

while read -r line; do
    line=${line%$'\r'} # in case lines end in \r\n. Otherwise,you can remove this line
    case $line in
        \>QDN* | TYPE* ) printf %s "${line#*;};" ;;
        SNPA* ) line=${line#*;}; printf %s "${line%%;*};" ;;
        OPTIONS* ) read -r line && printf '%s\n' "$line" ;;
    esac
done < file.txt

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。