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