【问题标题】:"(" char doesn't work in PowerShell"(" 字符在 PowerShell 中不起作用
【发布时间】:2014-02-17 08:24:48
【问题描述】:

我无法让它工作。它不喜欢 "(" char;

我该如何解决?

 Dir | Rename-Item -NewName { $_.name -replace "(","" }

如何在 PowerShell 中处理这种类型的特殊字符?

【问题讨论】:

  • 我没有使用powershell 的经验,因为像这里的大多数其他用户一样,我在 Linux 上工作并使用像 bash 这样的标准 shell。但这在所有环境中都应该是相同的:您必须“转义”具有控制意义的特殊字符。所以寻找如何在powershell中转义字符,很可能是backslashDir | Rename-Item -NewName { $_.name -replace "\(","" }。但话又说回来:如果某事是典型的,MS 总是以另一种方式做事,所以它很可能是你需要使用的另一个角色。检查文档。
  • @arkascha 请调低不专业的反 MS 态度。它并没有真正帮助回答这个问题,因为 .Net 确实在正则表达式中使用 `` 作为转义字符。
  • @vonPryz 我看不出问题是什么:这不是“态度”或任何东西。我提示了这是如何通常完成的(阅读:在其他 shell 中),并添加了一个提示,即这在 MS 环境中可能略有不同(您已确认)。所以它确实有帮助,因为它指出了正确的路径。
  • @arkascha 它真的只是偶然的帮助。 Powershell 中的转义字符是反引号。在这种情况下,您需要一个反斜杠来转义正则表达式中的特殊字符,而不是因为 shell 语法需要任何转义。如果您查看我给出的答案,您会发现实际上可以在不转义 ( 的情况下进行替换。

标签: powershell


【解决方案1】:

让我们试着分析一下这个问题。首先,创建一些包含括号的虚拟文件,

for($i=0;$i -le 4; ++$i) { set-content -path $("file($i).txt" -f $i) -value $i }
Output:
gci
    Directory: C:\temp\foo
Mode                LastWriteTime     Length Name
----                -------------     ------ ----
-a---         17.2.2014     10:34          3 file(0).txt
-a---         17.2.2014     10:34          3 file(1).txt
-a---         17.2.2014     10:34          3 file(2).txt
-a---         17.2.2014     10:34          3 file(3).txt
-a---         17.2.2014     10:34          3 file(4).txt

现在我们有了一些测试数据,让我们尝试运行提供类似错误消息的命令,

Dir | Rename-Item -NewName { $_.name -replace "(","" }

Rename-Item : The input to the script block for parameter 'NewName' failed.
Invalid regular expression pattern: (.
At line:1 char:27
+ Dir | Rename-Item -NewName <<<<  { $_.name -replace "(","" }
    + CategoryInfo          : InvalidArgument: (file(0).txt:PSObject) [Rename-Item], ParameterBind   ingException
    + FullyQualifiedErrorId : ScriptBlockArgumentInvocationFailed,Microsoft.PowerShell.Commands.Re   nameItemCommand

哎呀!错误消息说 使用了无效的正则表达式。这意味着-replace 不只是替换字符串,但它也支持regular expressions

为了让-replace 将输入视为文字而不是正则表达式,需要对输入进行转义。简单的方法是插入反斜杠\,但这很快就会变得乏味。幸运的是,有一个更简单的方法,因为 .Net Regex 类有一个内置的转义方法[Regex]::Excape()。像这样,

Dir | Rename-Item -NewName { $_.name -replace [regex]::escape("("),"" }
Output:
ls
    Directory: C:\temp\foo
Mode                LastWriteTime     Length Name
----                -------------     ------ ----
-a---         17.2.2014     10:34          3 file0).txt
-a---         17.2.2014     10:34          3 file1).txt
-a---         17.2.2014     10:34          3 file2).txt
-a---         17.2.2014     10:34          3 file3).txt
-a---         17.2.2014     10:34          3 file4).txt

【讨论】:

    【解决方案2】:

    @vonPryze 对问题的确切原因进行了很好的解释,但有一个更简单的解决方案。 -replace 运算符使用需要转义的正则表达式,但 .Replace() 字符串方法只使用字符串。因此,如果您不需要正则表达式,只需使用该方法即可,无需转义任何内容:

    dir | rename-item -NewName { $_.name.Replace("(","") }
    

    【讨论】:

    • 另外,我认为应该提到的是,Replace 方法区分大小写,但比-Replace 运算符快一点。
    【解决方案3】:
    Dir | Rename-Item -NewName { $_.name -replace "\(","" } # This works 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-05-23
      • 1970-01-01
      • 2019-04-09
      • 2012-10-05
      • 1970-01-01
      • 2014-12-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多