1

私は Tcl スクリプトを書いていますが、その一部には、文字列パターンを含む最初の行を別の行に置き換えることが含まれます。次のように、Tcl内のbashコマンドとしてsedを使用して実行しました。

exec bash -c {sed 0,/Apple/{s/Apple/Banana/ File}

私の質問は、Tclコマンドを使用してこれを行う直接的な方法はありますか?また、Tcl内で多くのBashコマンドを使用することは間違っているか、推奨されていませんか?

ありがとう

4

4 に答える 4

5

regsubまさにこれのためのコマンドがあります:

regsub -- {Apple} $line Banana line

これが公式ドキュメントです。

また、ファイルの最初の行を読むのに助けが必要な場合は、このページが役立つかもしれません。

于 2013-01-31T21:49:00.013 に答える
1

[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.
于 2013-02-01T20:21:55.143 に答える
0

テキストのブロック内の文字列を置き換える場合:

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
于 2013-02-01T18:57:38.970 に答える
0

まず、sedhere に手を差し伸べるのは ( の宣言的な表現力のため) きれいに見えますsedが、冗長であり、各「可動部分」を追加すると複雑さが増すため、プログラムのメンテナンスがより困難になります。

基本的に、プレーンな Tcl でスニペットを再実装するために必要な手順は次のとおりです。

  1. ソース ファイルを開きます。
  2. ファイルのチャネルを繰り返し呼び出しgetsて、ファイルからデータを 1 行ずつ読み取ります。
  3. 「Apple」を「Banana」に置き換えようとする、適切に構成された呼び出しをregsub各行で実行します。
  4. への呼び出しがregsub1 以上を返すとすぐに、文字列が正規表現と一致したことを意味し、ファイル読み取りループを終了します。

残りの実装は、データで何をしているかによって異なります。

第 2 に、Tcl スクリプトから実行することを選択した場合でも、Tcl のコマンドはコマンド パイプラインとストリーム リダイレクトを単独で処理できるためsed、ここでシェルを使用する必要はありません。exec

現在のアプローチのもう 1 つの明らかではない問題は、あるスクリプト (の場合sed) を別のスクリプト (シェルの場合) にインライン化すると、悪夢のようなエスケープが簡単に発生する可能性があることです: ソース パターンまたは置換パターンのいずれかが任意のデータであり、一重引用符と二重引用符だけでなく、空白文字も含みます。

第 3 に、シェルに渡すスクリプトにバシズム必要な場合を除いて、シェルbashを呼び出す必要がある場合は、絶対に呼び出さないでください。他のすべての 99.9% のケースでは、代わりに呼び出す必要があります。これは、実行するスクリプトの POSIX シェル セマンティクスを実装することが保証されている標準シェルへの標準パスです。この理由は、特定のシステム (特に、Debian および少なくともその一部の派生物) が別のシェル (Debian では ) にリンクされているためです。このシェルにはインタラクティブな機能がありませんが、代わりにスクリプトの起動と実行が高速化されています。/bin/sh/bin/shdashbash

于 2013-02-02T07:01:26.590 に答える