![如何从管道的输出中回显子字符串?](https://linux22.com/image/133231/%E5%A6%82%E4%BD%95%E4%BB%8E%E7%AE%A1%E9%81%93%E7%9A%84%E8%BE%93%E5%87%BA%E4%B8%AD%E5%9B%9E%E6%98%BE%E5%AD%90%E5%AD%97%E7%AC%A6%E4%B8%B2%EF%BC%9F.png)
我发现这里如何在 bash 中提取子字符串,但我不知道如何在管道之后应用它。例如:
some func | echo ${string:12:5}
如何将 的输出分配some func
给变量string
?
答案1
回答
如果您只想从 中提取输出some_func
,则无需将其存储在变量中,只需将输出发送到cut
该变量即可提取请求的字符:
some_func | cut -c 12-16
解释
cut
stdin
将根据指定的选项 提取并提取请求的范围。
-c
表示范围以字符指定。
12-16
字符以 index 开头的范围1
,而不是以0
.
因此,这将采用位置12
、13
、14
和15
处的字符16
。
作为斯蒂芬·查泽拉斯我留下了疑问,请注意,这适用于每一行输入,而不仅仅是第一行。
答案2
${string:offset:length}
是一个参数扩展运算符,可扩展到变量中的字符范围$string
。
为了得到一系列字节从输入中(这也适用于单字节字符),您可以使用:
func | tail -c +12 | head -c 5
获取从第 12 个字节开始的 5 个字节(从 1 开始的偏移量)。选项-c
不是head
标准的,但很常见。
func
请注意,在输出第 16 个字节后,它可能会被杀死,因为head
在输出这 5 个字节后将退出,并且tail
如果它尝试在此之后写入更多数据,则会被杀死,这将波及到func
.
您还可以这样做:
func | dd bs=1 skip=11 count=5 2> /dev/null
2> /dev/null
是为了避免最后出现状态消息。但这会抑制所有错误。使用 GNU dd
,您可以将其替换为status=none
仅抑制状态。
对于较大的 值length
,效率会较低,因为它一次读取一个字节。再次使用 GNU dd
,您可以通过执行以下操作来避免这种情况:
func | dd iflag=count_bytes,skip_bytes,fullblock skip=11 bs=64k count=5M status=none
每次读取最多 64KiB,以获得 5MiB 字节的数据。
现在,对于那些用字符(单字节或多字节)而不是字节来表示的偏移量和长度,这变得更加复杂。
一个选项是将整个输出存储在变量中并使用${var:offset:length}
运算符正如其他人所表明的。但这意味着将整个输出存储在内存中。使用var=$(func)
还意味着尾随换行符将被丢弃。
另一种选择是使用bash
'sread -N
读取给定数量的人物:
func | {
IFS= read -rN 11 discarded
IFS= read -rN 5 data
printf '%s\n' "$data"
}
或者使用perl
(对于大数据来说效率稍高):
func | perl -Mopen=locale -sne '
BEGIN{$total = $o + $n; $/ = \$total}
print substr($_, $o); exit' -- -o=10000 -n=5000000
答案3
string="$(func)"
echo "${string:12:5}"