Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PowerShell Select-String context doesn't work with output piped from non-PowerShell command

I'm trying to use Select-String in PowerShell to look at the results from docker inspect command, but the Context property doesn't seem to be working properly.

As you know, docker inspect returns normal JSON as output, e.g.:

[
    {
        "Id": "c8a5810c62d8dbea11335be561522b4a3df53b9ddcae5531ae06483926c5f992",
        "Created": "2018-07-31T17:16:53.8689464Z",
        "Path": "nginx",
        "Args": [
            "-g",
            "daemon off;"
        ],
        "State": {
            "Status": "running",
            "Running": true,
            "Paused": false,
            "Restarting": false,
            "OOMKilled": false,
            "Dead": false,
            "Pid": 13613,
            "ExitCode": 0,
            "Error": "",
            "StartedAt": "2018-07-31T17:16:54.6460418Z",
            "FinishedAt": "0001-01-01T00:00:00Z"
        },
        ...
    },
    ...
]

Running sls (alias for Select-String) without any additional arguments:

enter image description here

And running it with Context:

enter image description here

As you can see, the output is the same, and I don't see the before and after lines in my output

I'm able to use grep to do what I want; e.g.,

docker inspect devtest | grep Mounts -B 5 -A 5

Output of grep:

enter image description here

But I was wondering why Select-String doesn't work.


Update

As @iRon suggested, I even tried saving the output to a file and then use Select-String on the file (sample file):

enter image description here

So, I'm really confused as to what's happening. Because for @iRon it's working properly.


Update 2

I noticed that if I do something like this:

$result = $json | Select-String "Mounts" -Context 5`

then when I look at $result[0].Context.PreContext (and PostContext), they contain the before and after lines in the input, but for some unknown reason, they're not printed to the console

like image 735
Farzad Avatar asked Feb 23 '26 01:02

Farzad


1 Answers

As said, I do not have Docker installed (as I am on Windows 10 Home but I am currently trying to install Dock Toolbox).
Anyways, I think you should be able to exclude docker from your question by splitsing the command:

$Json = docker inspect devtest
$Json | Select-String "Mounts" -Context 5

Investigate the $Json string and build a MCVE question like:
"How do I use Select-String -Context on a raw text file?"

Question:

I have the following raw Json string:

$Json = @'
[
    {
        "Id": "c8a5810c62d8dbea11335be561522b4a3df53b9ddcae5531ae06483926c5f992",
        "Created": "2018-07-31T17:16:53.8689464Z",
        "Path": "nginx",
        "Args": [
            "-g",
            "daemon off;"
        ],
        "Mounts": [
            {
                "Type": "bind",
                "Source": "/tmp/source/target",
                "Destination": "/app",
                "Mode": "ro",
                "RW": false,
                "Propagation": "rprivate"
            }
        ],
        "State": {
            "Status": "running",
            "Running": true,
            "Paused": false,
            "Restarting": false,
            "OOMKilled": false,
            "Dead": false,
            "Pid": 13613,
            "ExitCode": 0,
            "Error": "",
        }
    }
]
'@

If I run $Json | Select-String "Mounts" -Context 5 I do not get the expected results.

Answer

The Select-String cmdlet expects a stream (an array) of lines and not a raw text object separated by Carriage Returns and/or LineFeeds (or whatever your operating system uses for a NewLine).
This means that a line (a single string item in the array) could contain even a NewLine character but is still considered as a single line by the Select-String cmdlet.
In other words, the docker inspect devtest output is concidered as one single line by the Select-String cmdlet

The solution is to split your text into an array of string (lines), String[]:

$Json -Split "[\r\n]+" | Select-String "Mounts" -Context 5

Result:

  "Path": "nginx",
  "Args": [
  "-g",
  "daemon off;"
  ],
> "Mounts": [
  {
  "Type": "bind",
  "Source": "/tmp/source/target",
  "Destination": "/app",
  "Mode": "ro",

Your test.json file works fine as well:

Get-Content .\test.json | Select-String "Mounts" -Context 5

                  "UpperDir": "/var/lib/docker/overlay2/232d9803e4cdb9ec031561cfae7589a43a7fdc06e0517cc3f17417e44d5174fb/diff",
                  "WorkDir": "/var/lib/docker/overlay2/232d9803e4cdb9ec031561cfae7589a43a7fdc06e0517cc3f17417e44d5174fb/work"
              },
              "Name": "overlay2"
          },
>         "Mounts": [],
          "Config": {
              "Hostname": "c8a5810c62d8",
              "Domainname": "",
              "User": "",
              "AttachStdin": false,
like image 149
iRon Avatar answered Feb 25 '26 15:02

iRon