私は here bashで部分文字列を抽出する方法を見つけましたが、これをパイプの後に適用する方法について迷っています。例えば:
some func | echo ${string:12:5}
some func
の出力を変数string
に割り当てるにはどうすればよいですか?
_${string:offset:length}
_は、_$string
_変数の文字の範囲に展開されるパラメーター展開演算子です。
入力からbytesの範囲を取得するには(シングルバイト文字にも適用されます)、以下を使用できます。
_func | tail -c +12 | head -c 5
_
12バイト目から始まる5バイトを取得します(1ベースのオフセット)。 head
の_-c
_オプションは標準ではありませんが、かなり一般的です。
func
は、16バイト目を出力した後、いつか強制終了される可能性があることに注意してください。これらの5バイトを出力した後、head
が終了し、その後、さらにデータを書き込もうとすると、tail
が強制終了され、func
に波及します。
次のこともできます:
_func | dd bs=1 skip=11 count=5 2> /dev/null
_
_2> /dev/null
_は、最後のステータスメッセージを回避するためのものです。ただし、すべてのエラーが抑制されます。 GNU dd
を使用すると、これを_status=none
_に置き換えることで、ステータスのみを抑制できます。
length
の値が大きい場合、一度に1バイトを読み取るため、効率が低下します。 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
の_read -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
_
some_func
からの出力のみを抽出する場合は、変数に保存する必要はありません。出力をcut
に送信するだけで、要求された文字を抽出できます。
some_func | cut -c 12-16
cut
はstdin
を受け取り、指定されたオプションに基づいて要求された範囲を抽出します。
-c
範囲が文字で指定されていることを意味します。
12-16
文字が1
ではなく、インデックス0
で始まる範囲。
したがって、これは12
、13
、14
、15
および16
の位置にある文字を受け取ります。
StéphaneChazelas が私に残ったので、これは最初の行だけでなく、入力の各行でも機能することに注意してください。
string="$(func)"
echo "${string:12:5}"