2

strtok を使用して配列内の文字として表されるパイプ (|) と OR 記号 (||) の両方を含むシェル コマンドを分割しようとしていますが、OR コマンドは 2 つのパイプが隣り合っている可能性もあります。具体的には、いつ |、;、&&、または || かを知る必要があります。コマンドで表示されます。

strtok で 1 つの区切り記号が終わり、別の区切り記号が始まる場所を指定する方法はありますか? 通常、区切り記号は 1 文字の長さであり、間にスペースや何も入れずにすべてリストするだけです。

ああ、改行は有効な区切り文字ですか? それとも strtok はスペースのみを行いますか?

4

3 に答える 3

3

最後の質問から始めて:はい、strtok改行を区切り文字として問題なく使用できます。

残念ながら、最初の質問に対する答えは、あまり肯定的ではありません。strtokはすべての区切り文字を同等に扱い、単一の区切り文字と任意の数の連続する区切り文字を区別しません。つまり、|&;区切り文字として指定すると、|||||||||or&&&または&|&|;すべてがまったく同じように扱われます。

私はもう少し先に進みます: 私は四肢に出てstrtok、シェルコマンドを構成要素に分割するのには単に適していないという事実として述べます.使用可能な結果を​​生み出すこの仕事。

特に、区切り記号として機能するものは何もありません。目的のために、&|、および||は独自のトークンです。シェルに提供される文字列では、それらを「考える」方法で区切り文字としての資格があるとは限りませんstrtok

strtok区切り文字以外の何物でもない区切り文字で区切られたトークンを対象としています。がトークンを読み取るときstrtok、それらの間の区切り文字は完全に無視されます (さらに言えば、破棄されます)。シェルの場合、文字列 likeは実際には 3 つのトークンです -- 、、a|bが必要です-- それらの間に安全に上書きしたり無視したりできるものは何もありません -- しかし、それは がどのように動作するかの要件です。最初の を配信するために、次の文字 (この場合は) を.で上書きします。次に、そのパイプを回復して、次のトークンがどうあるべきかを伝える方法がありません。a|bstrtokstrtoka|'\0'

おそらく、代わりに貪欲なトークナイザーが必要だと思います。つまり、トークンにできる最長の文字列を構築し、現在のトークンの一部にならない文字に遭遇すると停止します。次のトークンを要求すると、(必然的に) 何もスキップ/無視せずに、前のトークンの終わりの後の最初の文字から開始します (もちろん、引用されていない空白のようなものに遭遇した場合)どういうわけか、おそらくそれをスキップします)。

于 2013-01-16T03:52:43.843 に答える
1

strtok()基本的な汎用解析関数です。より高度な解析については、その使用はお勧めしません。

たとえば、「|」の場合、次の文字を調べて「|」が見つかったかどうかを判断する必要があります。または「||」。

私は、小さな言語インタープリターの作成を含め、この性質の解析を大量に行いました。小さなタスクに分割すれば、それほど難しくありません。ただし、この場合は独自の解析ルーチンを作成することをお勧めします。

そして、はい、改行文字は有効な区切り文字です。

于 2013-01-16T03:50:49.770 に答える
1

あなたの目的のために、strtok()使用する正しいツールではありません。区切り文字を破棄するため、誰かがls|wc. パイプ、セミコロン、アンパサンド、またはスペースである可能性があります。また、隣接する複数の区切り文字を 1 つの区切り文字の一部として扱います。

とを見てstrspn()くださいstrcspn()。両方とも標準 C にあり、非破壊的なstrtok().

strtok()区切り文字として改行を使用することは非常に満足です。実際、区切り文字の 1 つとして を除く任意の文字を'\0'使用できます。

strtok()スレッド セーフや、ライブラリ コードでの使用は非常に賢明ではないという事実など、 の使用に非常に慎重になる理由は他にもあります。

于 2013-01-16T03:53:05.227 に答える