4

I am using Ack version 2.04, in PowerShell. I want to search texts like "jsonClass":"Page" (quotes included) inside text files.

I can't seem to get the quoting and escaping correct.

ack -c --match '"jsonClass":"Page"'

It doesn't work in PowerShell. I guess ack's picking up the single quotes as well.

Escaping the double quotes gives an invalid regex error:

ack -c --match "\"jsonClass\":\"Page\""
  Invalid regex '\':
  Trailing \ in regex m/\/ at C:\CHOCOL~1\lib\ACK2~1.04\content\ack.pl line 315

I tried the literal option as well, but I think ack's interpreting the colon as file parameters.

ack -c -Q --match "jsonClass":"Page"
  ack.pl: :Page: No such file or directory

What am I missing?

I am using PowerShell v2.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
sas1138
  • 338
  • 5
  • 16

3 Answers3

6

To complement JPBlanc's effective answer with a PowerShell v3+ solution:

When invoking external programs such as ack , use of the so-called stop-parsing symbol, --%, makes PowerShell pass the remaining arguments through as-is, with the exception of expanding cmd.exe-style environment-variable references such as %PATH%:

ack --% -c --match "\"jsonClass\":\"Page\""

This allows you to focus on the escaping rules of the target program only, without worrying about the complex interplay with PowerShell's own parsing and escaping.

Thus, in PowerShell v3 or higher, the OP's own 2nd solution attempt would have worked by passing --% as the first parameter.

See Get-Help about_Parsing.


Note that the exact equivalent of the above command without the use of --% (that also works in PSv2 and is generally helpful if you want to include PowerShell-expanded variables / expressions in other arguments) would look like this:

ack -c --match '"\"jsonClass\":\"Page\""'

That is, the entire argument to be passed as-is is enclosed in single quotes, which ensures that PowerShell doesn't interpret it.

Note the inner enclosing " that aren't present in JPBlanc's answer (as of this writing). They guarantee that the argument is ultimately seen as a single argument by ack, even if it contains whitespace.

Community
  • 1
  • 1
mklement0
  • 382,024
  • 64
  • 607
  • 775
  • I am using PowerShell v2, and the above escaping isnt solving it, because it seems the args passed to ack is also including the back quote – sas1138 Oct 15 '16 at 12:24
  • @sas1138: I've rewritten the answer. It is now only helpful to PSv3+ users, but since you haven't tagged your post as v2-only (please keep it that way now), I figured I'd show a PSv3+ alternative that may be helpful to future readers. (The mistake of my original answer was that I was trying to fix your _PowerShell solution attempt_ rather than solve your original problem; note that the backticks would _not_ have been passed to `ack`, however, because the backtick is PS' _own_ escape char.) – mklement0 Oct 15 '16 at 13:04
  • thanks, i tried to edit, but i didn't have enough privileges to edit posts yet – sas1138 Oct 15 '16 at 14:01
  • @sas1138 You should always be able to edit your _own_ posts, however (if you're signed in). (Just to amend my previous comment: I've since added a PSv2 solution too.) – mklement0 Oct 15 '16 at 14:03
4

If ack is a function it could happen that -c is interpreted by PowerShell. Can you test the following?

ack '-c' '--match' '"jsonClass":"Page"'

-c --match should be interpreted as --match is the value of parameter c in function ask.

If it's an EXE file, try:

ack -c --match '\"jsonClass\":\"Page\"'
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
JPBlanc
  • 70,406
  • 17
  • 130
  • 175
  • this doesnt seem to be the issue. – sas1138 Oct 15 '16 at 12:13
  • I tried -c without the quotes on simpler patterns and it's returning expected results. `ack -c -Q --match "Page"` – sas1138 Oct 15 '16 at 12:14
  • 3
    `ack` is a Perl script/module. The backslashes are needed for when the string is processed by Perl. Either `'\"jsonClass\":\"Page\"'` or ``"\`"jsonClass\`":\`"Page\`""`` will work. – Ansgar Wiechers Oct 15 '16 at 12:37
  • @ansgar-wiechers yes i had also zeroed down on the first pattern, via trail and error. Please post this as an answer. – sas1138 Oct 15 '16 at 12:45
  • 1
    Good answer, but to fully replicate _raw_ argument `"\"jsonClass\":\"Page\""`, I suggest enclosing the contents of the single-quoted string in double quotes: `'"\"jsonClass\":\"Page\""'`. It makes no difference with the string at hand, which doesn't contain whitespace, but in other cases it may. To add to @AnsgarWiechers' clarification: on Windows, `ack` is implemented as a batch file (`ack.cmd`) that calls `perl.exe` with script `ack.pl`. – mklement0 Oct 15 '16 at 13:19
1

In Powershell you can always use ' quote to handle inner " without problems.

But if you need to use " for a string (to interpolate a variable, for instance), you can escape them with `

$myvar = 'test'
$formatted = "{`"value`":`"$myvar`"}"

Write-Host $formatted
# output: {"value":"test"}
andrew.fox
  • 7,435
  • 5
  • 52
  • 75