私は Tcl スクリプトを書いていますが、その一部には、文字列パターンを含む最初の行を別の行に置き換えることが含まれます。次のように、Tcl内のbashコマンドとしてsedを使用して実行しました。
exec bash -c {sed 0,/Apple/{s/Apple/Banana/ File}
私の質問は、Tclコマンドを使用してこれを行う直接的な方法はありますか?また、Tcl内で多くのBashコマンドを使用することは間違っているか、推奨されていませんか?
ありがとう
regsub
まさにこれのためのコマンドがあります:
regsub -- {Apple} $line Banana line
また、ファイルの最初の行を読むのに助けが必要な場合は、このページが役立つかもしれません。
[string]
コマンドの組み合わせでこれを行うことができます。
proc replaceFirst {text find replace} {
set idx [string first $find $text]
if {$idx == -1} {return $text} ;# search string not found in text
set end [expr {$idx + [string length $find] - 1}]
string replace $text $idx $end $replace
}
replaceFirst "I hear Apple makes many popular Apple products." Apple Banana
# => I hear Banana makes many popular Apple products.
テキストのブロック内の文字列を置き換える場合:
set text [string map {Apple Banana} $text]
ファイル内の文字列を更新する場合、fileutil
パッケージにはチケットのみが含まれますfileutil::updateInPlace
::
package require fileutil
proc processLine {line} { return [string map {Apple Banana} $line] }
fileutil::updateInPlace file.txt processLine
このstring map
コマンドは一度に多くの文字列を置き換えることができることに注意してください。
string map {Apple Banana Monkey Ape Coke Pepsi} $text
文字列マップがAppleのすべてのインスタンスを置き換えることが判明しましたが、これはAhmedが望んでいたものではありません(それを指摘してくれたGlennに感謝します)。acheong87のregsubソリューションを使用する必要があります。
package require fileutil
proc processLine {line} { return [regsub -- {Apple} $line "Banana"] }
fileutil::updateInPlace file.txt processLine
まず、sed
here に手を差し伸べるのは ( の宣言的な表現力のため) きれいに見えますsed
が、冗長であり、各「可動部分」を追加すると複雑さが増すため、プログラムのメンテナンスがより困難になります。
基本的に、プレーンな Tcl でスニペットを再実装するために必要な手順は次のとおりです。
gets
て、ファイルからデータを 1 行ずつ読み取ります。regsub
各行で実行します。regsub
1 以上を返すとすぐに、文字列が正規表現と一致したことを意味し、ファイル読み取りループを終了します。残りの実装は、データで何をしているかによって異なります。
第 2 に、Tcl スクリプトから実行することを選択した場合でも、Tcl のコマンドはコマンド パイプラインとストリーム リダイレクトを単独で処理できるためsed
、ここでシェルを使用する必要はありません。exec
現在のアプローチのもう 1 つの明らかではない問題は、あるスクリプト (の場合sed
) を別のスクリプト (シェルの場合) にインライン化すると、悪夢のようなエスケープが簡単に発生する可能性があることです: ソース パターンまたは置換パターンのいずれかが任意のデータであり、一重引用符と二重引用符だけでなく、空白文字も含みます。
第 3 に、シェルに渡すスクリプトにバシズムが必要な場合を除いて、シェルbash
を呼び出す必要がある場合は、絶対に呼び出さないでください。他のすべての 99.9% のケースでは、代わりに呼び出す必要があります。これは、実行するスクリプトの POSIX シェル セマンティクスを実装することが保証されている標準シェルへの標準パスです。この理由は、特定のシステム (特に、Debian および少なくともその一部の派生物) が別のシェル (Debian では ) にリンクされているためです。このシェルにはインタラクティブな機能がありませんが、代わりにスクリプトの起動と実行が高速化されています。/bin/sh
/bin/sh
dash
bash