我正在尝试拆分包含管道(|)和OR符号(||)的shell命令,这些命令用strtok表示为数组中的字符,除了OR命令也可以是旁边的两个管道彼此。具体来说,我需要知道何时|,;,&&或||出现在命令中。
有没有办法指定一个分隔符的结束位置,另一个分隔符从strtok开始,因为我知道分隔符通常是一个字符长,你只需将它们全部列出,没有空格或介于两者之间。
哦,换行符是一个有效的分隔符吗?或者strtok只做空格吗?
答案 0 :(得分:3)
从上一个问题开始:是的,strtok
可以使用换行符作为分隔符而没有任何问题。
不幸的是,你的第一个问题的答案并不是那么积极。 strtok
将所有分隔符都视为相等,并且无法区分单个分隔符和任意数量的连续分隔符。换句话说,如果您将|&;
作为分隔符,则会以完全相同的方式处理|||||||||
或&&&
或&|&|;
。
我会更进一步:我会说出一个事实,strtok
根本不适合将shell命令分解为组成部分 - 我很确定没有办法将它用于这项可以产生有用结果的工作。
特别是,您没有只作为分隔符的任何内容。出于您的目的,&
,|
和||
是他们自己的令牌。在提供给shell的字符串中,您不一定有任何符合strtok
“认为”它们的方式的分隔符。
strtok
面向由除分隔符之外的 nothing 分隔符分隔的标记。当strtok
读取令牌时,它们之间的分隔符完全被忽略(并且就此而言被破坏)。对于shell,像a|b
这样的字符串实际上是三个标记 - 您需要a
,|
和b
- 它们之间没有{{1}可以安全地覆盖和/或忽略 - 但这是strtok
如何工作的要求。为了向您提供第一个strtok
,它会使用a
覆盖下一个字符(本例中为|
)。然后它无法恢复该管道以告诉您下一个令牌应该是什么。
我认为你可能需要一个贪婪的标记器 - 即构建可以是标记的最长字符串的一个,并在遇到不能成为当前标记一部分的字符时停止。当你要求下一个标记时,它从前一个标记结束后的第一个字符开始,没有(必然)跳过/忽略任何东西(当然,如果它遇到类似白色空间但没有被引用的东西不知何故,它可能会跳过它。)
答案 1 :(得分:1)
strtok()
是一个基本的,通用的解析函数。对于更高级的解析,我不建议使用它。
例如,在“|”的情况下,你真的需要检查下一个字符以确定你是否找到了'|'或'||'。
我已经完成了大量的这种解析,包括编写一个小语言解释器。如果你把它分解成更小的任务并不难。但我的建议是在这种情况下编写自己的解析例程。
而且,是的,换行符是有效的分隔符。
答案 2 :(得分:1)
出于您的目的,strtok()
不是正确使用的工具;它会破坏分隔符,因此如果有人键入ls|wc
,您无法分辨令牌末尾的内容。它可能是一个管道,一个分号,和号,或一个空间。此外,它将多个相邻分隔符视为单个分隔符的一部分。
查看strspn()
和strcspn()
;两者都是标准C,是strtok()
的非破坏性亲属。
strtok()
非常乐意使用换行符作为分隔符;实际上,除'\0'
之外的任何字符都可以用作分隔符之一。
使用strtok()
非常谨慎还有其他原因,例如线程安全以及在库代码中使用它是非常不明智的事实。