Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/vb.net/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/google-maps/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Vb.net 按空格拆分shell命令,但允许使用引号将多个单词参数括起来_Vb.net - Fatal编程技术网

Vb.net 按空格拆分shell命令,但允许使用引号将多个单词参数括起来

Vb.net 按空格拆分shell命令,但允许使用引号将多个单词参数括起来,vb.net,Vb.net,我想编写一个像命令shell一样工作的应用程序(请求一个命令,执行它,然后请求下一个命令,重复)。然而,当我试图将书面命令拆分为单独的部分时,我立即失败了 我不仅要在空格处拆分命令,而且要允许参数包含空格,只要将它们放在双引号之间 我无法找出我的代码出了什么问题,即使我逐行检查它 Module Module1 Dim _exit As Boolean = False Dim prompt As String = "" Dim Title As String = ""

我想编写一个像命令shell一样工作的应用程序(请求一个命令,执行它,然后请求下一个命令,重复)。然而,当我试图将书面命令拆分为单独的部分时,我立即失败了

我不仅要在空格处拆分命令,而且要允许参数包含空格,只要将它们放在双引号之间

我无法找出我的代码出了什么问题,即使我逐行检查它

Module Module1
    Dim _exit As Boolean = False
    Dim prompt As String = ""
    Dim Title As String = ""

    Sub Main()
        Console.Title = Title
        While Not _exit
            Console.Write(prompt)
            Dim returned As String = Console.ReadLine
            Dim parts() As String = split_with_string(returned, False)
            If parts(0) = "exit" Then
                _exit = True
            ElseIf parts(0) = "" Then
                'Space for Commands
            Else
                Console.WriteLine("Unknown Command")
            End If
        End While
    End Sub

    Private Function secindex(ByVal str As String, character As Char)
        Return str.IndexOf(character, str.IndexOf(character) + 1)
    End Function

    Private Function split_with_string(ByVal str As String, ByVal return_parts As Boolean)
        Dim returned As String = str
        Dim parts As New List(Of String)
_next:
        If returned.Length = 1 Then
            parts.Add(returned)
        ElseIf returned.StartsWith("""") Then
            parts.Add(returned.Substring(1, secindex(returned, """") - 1))
            returned = returned.Substring(secindex(returned, """") + 1)
        ElseIf returned.StartsWith(" ") Then
            returned = returned.Substring(1)
        Else
            If returned.Contains(" ") Then
                parts.Add(returned.Substring(0, returned.IndexOf(" ")))
                returned = returned.Substring(returned.IndexOf(" ") + 1)
            Else
                parts.Add(returned)
                returned = ""
            End If
        End If
        If Not returned.Length < 1 Then
            GoTo _next
        End If
        If return_parts Then
            For Each xx In parts.ToArray
                Console.WriteLine(xx)
            Next
        End If
        Return parts.ToArray
    End Function
End Module
模块1
Dim _以布尔值形式退出=False
Dim提示符为String=“”
Dim Title As String=“”
副标题()
Console.Title=Title
而不是退出
Console.Write(提示符)
Dim返回为String=Console.ReadLine
Dim parts()作为字符串=使用字符串分割(返回,False)
如果零件(0)=“退出”,则
_退出=真
其他部分(0)=“然后
'命令空间
其他的
Console.WriteLine(“未知命令”)
如果结束
结束时
端接头
私有函数secindex(ByVal str作为字符串,字符作为字符)
返回str.IndexOf(字符,str.IndexOf(字符)+1)
端函数
带字符串的私有函数拆分(ByVal str作为字符串,ByVal return作为布尔值)
Dim返回为String=str
将零件标注为新列表(字符串)
_下一步:
如果返回.Length=1,则
零件。添加(已返回)
ElseIf返回。然后用(“”)开始
parts.Add(返回的.Substring(1,secindex(返回的“”)-1))
returned=returned.Substring(secindex(returned,“”“”)+1)
ElseIf返回。然后用(“”)开始
returned=returned.Substring(1)
其他的
如果返回。包含(“”),则
parts.Add(返回的.Substring(0,返回的.IndexOf(“”))
returned=returned.Substring(returned.IndexOf(“”+1)
其他的
零件。添加(已返回)
returned=“”
如果结束
如果结束
如果未返回,则长度<1
下一个
如果结束
如果返回零件,则
对于每个xx部件,请参见图1
控制台写入线(xx)
下一个
如果结束
将零件返回到阵列
端函数
端模块

如果布尔值设置为true,我希望函数将结果写入控制台。

Regex使复杂字符串解析变得如此简单。它本身有一个陡峭的学习曲线,但由于它是许多语言和编程工具中可用的标准工具,您迟早应该熟悉它

例如,如果要获得如下所示的列表:

1
二
“这是三个”
“这是四个”
五
您可以使用如下代码:

Public Sub-Main()
Dim parts()作为String=ParseCommand(“一两”这是三“”这是四”“五”)
对于每个零件,将其作为零件中的字符串
控制台写入线(部分)
下一个
端接头
私有函数ParseCommand(作为字符串输入)作为字符串()
返回Regex.Matches(输入“(?!”)\S+|“[^”“]+”)。
(比赛的)演员。
选择(功能(m)m.Value)。
ToArray()
端函数
但是,如果希望删除引号,则输出如下所示:

1
二
这是三个
这是四
五
您可以对正则表达式模式进行一些调整,如下所示:

Private Function ParseCommand(作为字符串输入)作为字符串()
返回Regex.Matches(输入“(?(?!”)\S+)|“(?[^”“]+)”)。
(比赛的)演员。
选择(功能(m)m.组(“p”).值)。
ToArray()
端函数
如果您不熟悉正则表达式,它将使用一种模式来查找输入字符串中匹配的子字符串。在第一个示例中,它所寻找的模式是
(?!”)\s+|“[^”]+”
。因此,它在输入字符串中查找与该模式匹配的所有部分,并只返回那些匹配的子字符串。以下是该模式的含义:

  • (?!”)\S+
    -匹配任何不以
    开头的单词
    • (?!”
      -包含在
      (?!…)
      子句中的任何内容都被称为消极前瞻。这意味着无论接下来发生什么,都不能是该子句中列出的内容。在这种情况下,这意味着接下来发生的任何内容都不能以
      字符开头
    • \S
      -这是指任何非空格字符,因此任何不是空格、制表符或类似字符的字符
    • +
      -这意味着必须有一个或多个非空格字符
  • |
    -这意味着布尔或,意味着它可以匹配它前面的任何内容或它后面的任何内容
  • “[^”]+”
    -这匹配两个
    字符之间的所有单词,包括任何空格
    • -表示匹配必须以
      开头”
    • [^”]
      -包含在
      [^…]
      子句中的任何字符都是负数字符类。这意味着它可以是不是子句中列出的字符之一的任何字符。在这种情况下,它表示任何非
      的字符
    • +
      -这意味着必须有一个或多个非引号字符
    • -表示匹配必须以
第二种模式基本上是相同的,但它更高级一些,因为它使用命名组(例如,
(?子模式)
)来匹配整个匹配的某些部分