ksh88でHere-Stringsを使用できますか?

ksh88でHere-Stringsを使用できますか?

kshスクリプトの3つの変数のうちの1つから3つの単語を抽出したいと思います。 ksh93でこの行を使用しましたが、うまく動作します。

read A B C <<< $line

ksh88で上記のコマンドを実行すると、次のエラーが発生します。

syntax error at line ## : '<' unexpected

ksh88で同じことをどのように実行できますか?

答え1

ksh88いいえ、ここの文字列はおよびで使用できませんpdksh。ただし、最新ksh93(オリジナルのAT&T Korn Shell)および(mksh現在活発に開発されているpdkshスピンオフ)で利用可能です。

<<<はいksh93、、mkshGNU bash、およびzsh

あなたの具体的な質問...

read A B C <<< $line

...この問題を解決できます(Kornシェル)。

print -r -- $line |&
read -p A B C

これを使用することもできますが(POSIXシェル)、tmpfileのパフォーマンスが低下します(一方である可能性<<<があります)。

read A B C <<EOF
$line
EOF

しかし、単語を分離したい場合は、次のようにします。

set -A arrname -- $line

${arrname[0]}その後、代わりに使用し$A${arrname[1]}交換してください$B。 3つの要素に分割されても止まらないということだけです。したがって、$linefoo bar baz bla」の場合は$C「baz bla」が含まれ、${arrname[2]}「baz」がある場合は${arrname[3]}「bla」が含まれます。

ただし、位置パラメーターが不要な場合は、次のことができます。

set -- $line
A=$1; shift
B=$1; shift
C=$*

ただし、単語数が3個未満の場合はエラーが発生します(不明な場合は確認するかshift(潜在的に遅い)確認を最初に使用してください)。$line$#[[ $line = *' '*' '[! ] ]]

これはset … $lineワイルドカードも行います(上記のStéphaneに感謝します)、以前に必要ですset -o noglob(通常は後で以前の状態を復元できますset +o noglob)。

完全な公開:私はmksh開発者です。

答え2

いいえ、ここの文字列はzsh1991年2.0(および/またはUnixポート)から取得されましたrc。それぞれの作者は当時のアイデアを交換し、2人のうち誰がアイデアを持っているのか、彼のシェルの最初の真ん中に含めたのかはわかりません。

2.05b(2002)のbash、m+(2002)のksh93、R33(2008)のmksh、2.7(2009)のyashに追加されました。

ksh88には新機能はありません。

ここにある文書(<<)自体は、1970年代後半のBourne-shellからのものです。

read A B C一つ読んでください論理的行は非常に特定の方法で挿入され、A変数B(デフォルトはIFS空白文字1のみを含むややあまり具体的ではありませんC$IFSとバックスラッシュがエスケープおよび行連続文字として機能するため、これCも非常に複雑になります。なしで同じことをするのは非常に難しいでしょうread

とにかくここ<<<と同じで<<構文だけが異なります。

read A B C << EOF
$var
EOF

まったく同じ

read A B C <<< "$var" # note that some versions of bash need the quotes

すべての殻に。どちらの場合も、シェルは内容と追加された改行文字を含む削除された一時ファイルを生成します(一部のシェルは代わりにパイプを使用します)。それではread読んでください。論理的行(バックスラッシュで続く複数の物理行に存在する可能性があります)を入力し、複雑なルールを使用して変数を入力します。

$varto(SPC/TAB区切り)の最初の3ワードのみを割り当て $A$B$C

  • $IFSまだデフォルト値が含まれています。
  • 変数にバックスラッシュと改行文字が含まれていません。
  • この変数には3つの単語のみが含まれています。

最初の3つの単語に対して、次のことができます。

function split_into {
  typeset words IFS v i=0
  set -o noglob

  set -A words -- $1; shift
  for v do
    eval "$v=\${words[i]}"
    ((i += 1))
  done
}

split_into "$var" A B C
  
  

^IFS スペース文字、各POSIXはロケールに分類された文字であり、ksh88(POSIX仕様のベース)とほとんどのシェルで発生する[:space:]ように、これはまだSPC、TAB、およびNLに制限されています。$IFSこれに関して私が見つけた唯一のPOSIX互換シェルはですyashksh93bash5.0ベース)他のスペース(CR、FF、VTなど)も含まれていますが、シングルバイトスペースに制限されています(たとえば、Solaris)(一部の領域にはシングルバイトの切り捨て防止スペースが含まれています)

関連情報