2

我正在尝试分解一个shell命令,该命令包含管道(|)和用strtok表示为数组中字符的OR符号(||),除了OR命令也可以是两个相邻的管道。具体来说,我需要知道何时 |、;、&& 或 || 出现在命令中。

有没有办法指定一个分隔符在哪里结束,另一个在 strtok 中开始,因为我知道通常分隔符是一个字符长,你只需将它们全部列出,中间没有空格或任何东西。

哦,换行符是有效的分隔符吗?还是 strtok 只做空格?

4

3 回答 3

3

从你的最后一个问题开始:是的,strtok可以使用换行符作为分隔符没有任何问题。

不幸的是,您的第一个问题的答案几乎没有那么积极。strtok将所有分隔符视为相等,并且不区分单个分隔符和任意数量的连续分隔符。换句话说,如果您将|&;其作为分隔符,它将以完全相同的方式处理|||||||||&&&或全部。&|&|;

我会走得更远一点:我会冒险并陈述一个事实,即strtok根本不适合将 shell 命令分解成组成部分——我很确定没有办法将它用于这项工作将产生有用的结果。

特别是,您没有任何仅用作分隔符的东西。出于您的目的,&|||是它们自己的标记。在提供给 shell 的字符串中,您不一定有任何符合strtok“认为”它们的分隔符的条件。

strtok面向由分隔符分隔的标记,除了分隔符之外什么都不是。在strtok读取标记时,它们之间的分隔符被完全忽略(并且,就此而言,被销毁)。对于 shell,类似这样的字符串a|b实际上是三个标记——你需要a、 the|bthe——它们之间没有任何东西strtok可以安全地覆盖和/或忽略——但这是strtok工作方式的要求。为了给您提供第一个a,它会用 覆盖下一个字符(|在本例中为 )'\0'。然后它无法恢复该管道来告诉您下一个令牌应该是什么。

我认为您可能需要一个贪婪的标记器 - 即构建最长的可以作为标记的字符串,并在遇到不能成为当前标记一部分的字符时停止。当您要求下一个标记时,它从前一个标记结束后的第一个字符开始,而不会(必然)跳过/忽略任何内容(当然,如果它遇到未引用的空格之类的东西不知何故,它可能会跳过它)。

于 2013-01-16T03:52:43.843 回答
1

strtok()是一个基本的、通用的解析函数。对于更高级的解析,我不推荐使用它。

例如,在“|”的情况下,您确实需要检查下一个字符以确定您是否找到了“|” 或“||”。

我已经完成了大量的这种性质的解析,包括编写一个小型语言解释器。如果你把它分解成更小的任务,这并不难。但我的建议是在这种情况下编写自己的解析例程。

而且,是的,换行符是有效的分隔符。

于 2013-01-16T03:50:49.770 回答
1

出于您的目的,strtok()不是正确使用的工具;它会破坏分隔符,因此如果有人键入,您无法分辨令牌末尾的内容ls|wc。它可能是一个管道、一个分号和一个 & 符号,或者一个空格。此外,它将多个相邻分隔符视为单个分隔符的一部分。

strspn()strcspn(); 两者都在标准 C 中,并且是strtok().

strtok()很乐意使用换行符作为分隔符;事实上,除此之外的任何字符都'\0'可以用作分隔符之一。

使用 非常谨慎还有其他原因strtok(),例如线程安全以及在库代码中使用它是非常不明智的事实。

于 2013-01-16T03:53:05.227 回答