頭と尾のみを使用して文字列の一部を抽出する

頭と尾のみを使用して文字列の一部を抽出する

こんにちは。ヘッド、テール、パイプ(最終的にリダイレクト)のみを使用して、文字列の開始、中間、終了を抽出して出力する方法があるかどうか疑問に思います。

例: 次の文字列が与えられた場合、SHOWpijfirefjTHISezpijSTRINGコマンドは「SHOWTHISSTRING」を出力する必要があります。

私は次のことを試しました (head -c 4 mdp > /dev/tty) | (tail -c +13 mdp | head -c 4 > /dev/tty) | (tail -c 6 mdp > /dev/tty) 2>&1

ただし、常に同じ結果を返すわけではなく、順序付けされていない結果を提供することもできます。

ベストアンサー1

head非標準-cオプションをサポートし、固定バイト数を出力するように要求されたときに、入力が必要以上に読み取らないほどスマートな実装を使用できます。

string='SHOWpijfirefjTHISezpijSTRING'
printf %s "$string" | {
  head -c 4
  head -c 9 > /dev/null
  head -c 4
  tail -c 6
}

headGNUのhead組み込み関数では機能しますksh93が、headbusyboxでは機能しない方法を確認してください。を実行すると、strace -fe read busybox sh ./that-script次のようになります。

[pid  7739] read(0, "SHOWpijfirefjTHISezpijSTRING", 4096) = 28

1つ目はheadブロック全体を読み取ってすべての入力を消費し、そのうち4バイトを出力するため、次のコマンドとheadコマンドについてtail読み取ることができません。

GNUまたはksh93を使用している場合head

[pid 10293] read(0, "SHOW", 4)          = 4

また、文字1headの代わりにバイトtailが使用されるため、-c固定数の文字を報告するためにのみ使用でき、テキストは文字ごとに1バイトにエンコードされます。

ほとんどの最新のシェルには、文字位置に基づいて文字列を分割する演算子が組み込まれています。

たとえば、zsh または yash では次のようになります。

slice=${string[1,4]}${string[14,17]}${string[-4,-1]}

zshでは、次のように短縮できます。

slice=$string[1,4]$string[14,17]$string[-6,-1]

一部の部品を所定の位置から切り取ることができます。

$ string[5,13]= string[9,-7]=
$ print -r -- $string
SHOWTHISSTRING

または最新バージョンのksh93、または以下bashを使用してください。zshmksh

slice=${string:0:4}${string:13:4}${string: -6}

POSIX的に:

tmp=${string#?????????????}
slice=${string%"${string#????}"}${tmp%"${tmp#????}"}${string#"${string%????}"}

それにもかかわらずお勧めできます。このオプションは、一貫性を維持するためにいくつかの-c実装に追加され、文字が複数のバイトで構成される可能性があるという概念が出てくるずっと前に追加されました。head-ctail-ctail

おすすめ記事