パイピングbash文字列操作


9

私は他のいくつかのパイプbash文字列操作の質問を読みましたが、それらは特殊なアプリケーションのようです。

基本的に、以下をより簡単にする方法はありますか?

の代わりに

$ string='hello world'; string2="${string// /_}"; echo "${string2^^}"
HELLO_WORLD

何かのようなもの

$ echo 'hello world' | $"{-// /_}" | "${ -^^}"
HELLO_WORLD

編集私は速度を維持するために可能であればbash操作内に留まることに興味があります(スクリプトを大幅に遅くする傾向があるsed / awkとは対照的に)

Edit2:@jimmij

私は2番目の例が好きで、関数を作成することにしました。

bash_m() { { read x; echo "${x// /_}"; } | { read x; echo "${x^^}"; }; }
echo hello world | bash_m
HELLO_WORLD

1
この目的でsed / awkが遅いと思うのはなぜですか?彼らは来るのと同じくらい速いです。
mkc 2014年

1
@Ketan Sedとawkは別のプロセスであるため、bashが別のプロセスを起動せずにネイティブで実行できるものほど高速になることはありません。通常、この違いはほとんど目立ちませんが、シェルスクリプトでパフォーマンスの問題が発生する場合、通常は特定のループまたは計算が非常に多く繰り返され、何千ものプロセスの生成は、bashで単純な文字列操作をネイティブに行うよりも著しく遅くなります。
jw013 2014年

2
@ jw013これは、質問からの「hello world」などの短い文字列に当てはまりますが、文字列が非常に長い場合、trマニュアルで言うと、プロセスを生成する時間は、文字列操作の時間と比較して無視できるため、逆になりますsedawk専用されています。文字列が極端に長い場合、bashのマニュアル全体で言うと、内部的な制限があるため、bashは完全に処理を拒否できます。
jimmij 2014年

2
@ jw013私は、専用のツールとして、その後のbashの文字列操作のコードはあまり効率的であることを主張していますsedawktrまたは類似しました。少し前に編集したgena2xの回答を見て、この情報を正確に追加します:unix.stackexchange.com/questions/162221/…同じ質問に対するterdonの回答と比較したいかもしれません。ケースプロセスの生成には最も時間がかかります。自分でテストして結果を投稿できます。
jimmij 2014年

1
@Miatiなぜあなたはこの余分なものread x; echo $xがパフォーマンスに優れていると思いますか?構文は短くもきれいにも見えません。x=${x// /_}; x=${x^^}と同じことを行うには、より簡潔な方法{read x; echo ${x...です。パフォーマンスに関する限り、@ jimmijはtr/ sedより高速でbash、フォーク数が等しいことを指摘しています。パイプを使用すると、常に余分なプロセスが発生するため、フォークを保存するという引数は適用されなくなります。したがって、パイプを使用している場合は、sed/ trなどを使用します。bashで実行できる場合は、そうし、このread x; echo $xナンセンスをスキップします。
jw013 2014年

回答:


9

jimmijが言ったこと。彼の最後の例は、パイプされた式で試みていることに最も近いものです。

ここにそのテーマのバリエーションがあります:

echo 'hello world'|echo $(read s;s=${s^^};echo ${s// /_})

trかなり速いので、を使用する傾向があります。

echo 'hello world'|tr ' [:lower:]' '_[:upper:]'

bashがネストされたパラメーターの展開を許可しないのは残念だと思います。OTOH、このようなネストされた式を使用すると、コードが読みにくくなる可能性があります。可能な限り高速に実行するものが本当に必要な場合を除いて、PITAでデバッグする巧妙に見えるコードよりも、読みやすく、理解しやすく、保守しやすいコードを書く方が良いでしょう。そして、もしあなたが本当にない物事はあなたがコンパイルされたコード、使用されなければならない最高速度で行われる必要がないスクリプトを。


7

このような方法でパラメーター展開を渡すことはできません。シンボルをフォームのようにx使用する場合は、標準入力ではなく、実際の変数名である必要があります。少なくともはそうではありません。では、次の方法でネストされたパラメータの置換を実行できます。$"${x}"bashzsh

$ x=''hello world'
$ echo ${${x// /_}:u}
HELLO_WORLD

(注::uzsh同じ^^ですbash

bashでネストすることは不可能であり、私があなたが書いたものは得られる最高のものだと思いますが、奇妙な理由でパイプを方程式に含める必要がある場合は、これを試してみてください:

$ echo 'hello world' | { read x; echo "${x// /_}"; } | { read y; echo "${y^^}"; }
HELLO_WORLD

1
方法についての我々の最近の会話を考えるとtr/ sed速くよりもbash文字列処理での、そしてあなたは、標準のI / Oを経由して文字列を渡すためにパイプを使用しているかを考えると、私はとは対照的に、bashでこれらの操作を行うには、文字通りゼロ点を参照してくださいtr/ sed。なぜこれ| { read x; echo $x... }| sed同じことをするのとは対照的に、人は同じことをするのでしょうか?
jw013 2014年

1
@ jw013率直に言って、ほとんど意味がないと思います。強制的問題へのパイプに係合するようにOPを明示的に(それらの両方を求め、外部プログラムを使用したくなかったので、これは一例であり、echoそしてread少し速いので、原理的には、bashの組み込み関数です)。私がすでに回答で書いたように、OPが問題に持っているプログレッシブパラメーター操作は、bashでこのタスクについて私の意見で得ることができる最良のものです。とにかく問題はかなり学術的です。
jimmij 2014年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.