将特定字符串添加到数组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