将特定字符串添加到数组sed / awk / grep

我有这个

 ciscoFlashCopyStatus OBJECT-TYPE
        语法整数
                 {  
                 copyOperationPending(0),
                 copyInProgress(1),
                 copyOperationSuccess(2),
                 copyInvalidOperation(3),
                 copyInvalidProtocol(4),
                 copyInvalidSourceName(5),
                 copyInvalidDestName(6),
                 copyInvalidServerAddress(7),
                 copyDeviceBusy(8),
                 copyDeviceOpenError(9),
                 copyDeviceError(10),
                 copyDeviceNotProgrammable(11),
                 copyDeviceFull(12),
                 copyFileOpenError(13),
                 copyFileTransferError(14),
                 copyFileChecksumError(15),
                 copyNoMemory(16),
                 copyUnknownFailure(17),
                 copyInvalidSignature(18)
                 }
         MAX-ACCESS只读
        状态当前     

我想做的事

有些命令将VARIABLE每个名称复制到名为var的数组中

所以输出的例子

 echo“$ {var [0]}
 copyOperationPending

 echo“$ {var [1]}
 copyInProgress

 echo“$ {var [2]}
 copyOperationSuccess

等等..

任何想法我怎样才能做到这一点?

注意这是一个类似的问题,我之前曾问过一些事情是如何改变的,我不能再使用旧问题中提供的相同解决方案了。

使用grep

 mapfile -t var < <(grep -Po '^\s+\K[^ ]+(?= ?\(\d+\),?$)' file.txt) 
  • grep -P将使用PCRE(Perl兼容正则表达式)

  • grep -o将打印该行的匹配部分

  • ^\s+\K将匹配以空格开头的行, \K将丢弃匹配

  • [^ ]+将匹配我们想要的部分

  • (?= *\(\d+\))是零宽度正向前瞻模式,确保零或一个空格后跟( ,一个或多个数字)和零或一,在我们所需的匹配结束后

  • mapfile是一个内置的shell,用于创建数组。

     $ mapfile -t var < <(grep -Po '^\s+\K[^ ]+(?= ?\(\d+\),?$)' file.txt) $ echo "${var[0]}" copyOperationPending $ echo "${var[1]}" copyInProgress $ echo "${#var[@]}" 19 

您可以只使用字段grep行,并使用sed删除左括号后的所有内容。 生成的单词列表可以直接用于填充数组:

 var=($(grep input-file ' *[a-zA-Z]\+ \?([0-9]\+)' | sed 's/(.*//')) echo ${var[1]} 

grep中使用的正则表达式是:

  • 空格+ * :任意数量的空格(包括0)
  • [a-zA-Z]\+ :任意数量的字母(至少1个)
  • 空间+ \? :可选空间
  • ( :左括号
  • [0-9]\+ :任意位数(至少1位)
  • ) :右括号

对于您显示的特定文件,如果您只想要以copy开头的字符串,则只需执行以下操作:

 var=( $(grep -o 'copy[^(]*' file) ) 

你有:

 $ for((i=0;i<${#var[@]};i++)); do echo "${var[i]}"; done copyOperationPending copyInProgress copyOperationSuccess copyInvalidOperation copyInvalidProtocol copyInvalidSourceName copyInvalidDestName copyInvalidServerAddress copyDeviceBusy copyDeviceOpenError copyDeviceError copyDeviceNotProgrammable copyDeviceFull copyFileOpenError copyFileTransferError copyFileChecksumError copyNoMemory copyUnknownFailure copyInvalidSignature 

awk方法:

ARRAY=($(awk 'BEGIN{ORS=" "} /SYNTAX/ && /INTEGER/,/MAX-ACCESS/ {gsub(/SYNTAX|INTEGER|MAX-ACCESS.*|[[:blank:]]|{|}/,"");gsub(/\(/," (");for (i=1;i<=NR;i++) {if ($i~/\(|\)/) $i="" };print}' testfile.txt))

说明

  • 我们设置ARRAY =(...)结构,在其中使用命令替换$(...)来捕获内部awk命令到数组的输出。
  • 在MAX-ACCESS之前,从包含SYNTAX和INTEGER的行打印所有内容(以避免SYNTAX和INTEGER之间存在未知空间量的情况)。
  • 删除单词SYNTAX,INTEGER,MAX-ACCESS及其后的任何内容,删除空白行和两个花括号。
  • 将变量从变量(1)更改为变量(1),即将它们与空格分开。 在这一点上,我们将这些领域分成两部分。
  • 通过for循环查找具有花括号的字段并将其删除。 您可能会问,如果该字段包含空格,如(1)或(1),该怎么办? 不会只删除(在最后一个示例中为1?嗯,我们在此步骤之前删除了空格,所以这应该是安全的。

  • 最后打印所有内容,空格分隔而不是默认换行输出记录分隔符。 所有打印的内容都会进入arrays。

简化

让我们将所有内容放入awk脚本中:

 #!/usr/bin/awk -f BEGIN{ORS=" "} /SYNTAX/ && /INTEGER/,/MAX-ACCESS/ { gsub(/SYNTAX|INTEGER|MAX-ACCESS.*|[[:blank:]]|{|}/,""); gsub(/\(/," ("); for (i=1;i<=NR;i++) { if ($i~/\(|\)/) $i="" }; print } 

保存使该脚本可执行,并像这样运行:

 $ ARRAY=($(./varscript.awk testfile.txt )) $ echo ${ARRAY[0]} copyOperationPending $ echo ${ARRAY[1]} copyInProgress $ echo ${ARRAY[*]} copyOperationPending copyInProgress copyOperationSuccess copyInvalidOperation copyInvalidProtocol copyInvalidSourceName copyInvalidDestName copyInvalidServerAddress copyDeviceBusy copyDeviceOpenError copyDeviceError copyDeviceNotProgrammable copyDeviceFull copyFileOpenError copyFileTransferError copyFileChecksumError copyNoMemory copyUnknownFailure copyInvalidSignature 

使用gawk

 var=($(gawk '/{/,/}/ {if ($0 ~ /copy/) {match ($0, "[[:alpha:]]+", a); printf "%s\n",a[0]}}' )) 

使用perl

 var=($(perl -ne 'if (/copy/) {s/\s*([[:alpha:]]*).*/$1/g; printf "%s\n",$_}' )) 

awk

 $ var=($(gawk '/{/,/}/ {if ($0 ~ /copy/) {match ($0, "[[:alpha:]]+", a); printf "%s\n",a[0]}}' foo)) $ for((i=0;i<${#var[@]};i++)); do echo "${var[i]}"; done copyOperationPending copyInProgress copyOperationSuccess copyInvalidOperation copyInvalidProtocol copyInvalidSourceName copyInvalidDestName copyInvalidServerAddress copyDeviceBusy copyDeviceOpenError copyDeviceError copyDeviceNotProgrammable copyDeviceFull copyFileOpenError copyFileTransferError copyFileChecksumError copyNoMemory copyUnknownFailure copyInvalidSignature 

perl

 $ var=($(perl -ne 'if (/copy/) {s/\s*([[:alpha:]]*).*/$1/g; printf "%s\n",$_}' foo)) $ for((i=0;i<${#var[@]};i++)); do echo "${var[i]}"; done copyOperationPending copyInProgress copyOperationSuccess copyInvalidOperation copyInvalidProtocol copyInvalidSourceName copyInvalidDestName copyInvalidServerAddress copyDeviceBusy copyDeviceOpenError copyDeviceError copyDeviceNotProgrammable copyDeviceFull copyFileOpenError copyFileTransferError copyFileChecksumError copyNoMemory copyUnknownFailure copyInvalidSignature 

cat foo

 ciscoFlashCopyStatus OBJECT-TYPE SYNTAX INTEGER { copyOperationPending(0), copyInProgress(1), copyOperationSuccess (2), copyInvalidOperation (3), copyInvalidProtocol (4), copyInvalidSourceName (5), copyInvalidDestName (6), copyInvalidServerAddress (7), copyDeviceBusy (8), copyDeviceOpenError (9), copyDeviceError (10), copyDeviceNotProgrammable (11), copyDeviceFull (12), copyFileOpenError (13), copyFileTransferError(14), copyFileChecksumError(15), copyNoMemory (16), copyUnknownFailure(17), copyInvalidSignature(18) } MAX-ACCESS read-only STATUS current