# Parse output of command that interpret crystal script

**URL:** <https://forum.crystal-lang.org/t/parse-output-of-command-that-interpret-crystal-script/6942>\
**Category:** Help & Support\
**Created:** [June 18, 2024, 4:13pm UTC](https://forum.crystal-lang.org/t/parse-output-of-command-that-interpret-crystal-script/6942 "2024-06-18T16:13:26Z")\
**Posts on this page:** 16\
**Page:** 1

<div class="post-metadata">

**Author:** ![Fulgurance](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/fulgurance/32/1463_2.png) [@Fulgurance](https://forum.crystal-lang.org/u/Fulgurance)\
**Post date:** [June 18, 2024, 4:13pm UTC](https://forum.crystal-lang.org/t/parse-output-of-command-that-interpret-crystal-script/6942/1 "2024-06-18T16:13:26Z")

</div>

Hi guys, I have quite a specific question. I would like to know how can I parse the error of the result of running a crystal script by the command Process.run ?

Basically, I need to get the line number where the problem occurred, and get the error message. Because the ouput is formatted with colors and other things, I don’t know how to do ?

Because then I would like to show something else based on the information I have got.

So from that beginning, how should I do then ?

```crystal
processResult = IO::Memory.new

process = Process.run( "crystal error.cr",
                        error: processResult,
                        #error: :inherit,
                        shell: true)

```

---

<div class="post-metadata">

**Author:** ![Blacksmoke16](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/blacksmoke16/32/1241_2.png) [@Blacksmoke16](https://forum.crystal-lang.org/u/Blacksmoke16)\
**Post date:** [June 18, 2024, 4:35pm UTC](https://forum.crystal-lang.org/t/parse-output-of-command-that-interpret-crystal-script/6942/2 "2024-06-18T16:35:31Z")

</div>

Best bet would prob doing something like:

```crystal
output = IO::Memory.new

Process.run "crystal", ["run", "--no-color", "error.cr"], error: output

output_string = output.to_s

# Parse the data from output_string somehow

```

This’ll at least remove the coloring, so will make writing a regex or parser easier.

---

<div class="post-metadata">

**Author:** ![Ragmaanir](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/ragmaanir/32/1174_2.png) [@Ragmaanir](https://forum.crystal-lang.org/u/Ragmaanir)\
**Post date:** [June 18, 2024, 4:38pm UTC](https://forum.crystal-lang.org/t/parse-output-of-command-that-interpret-crystal-script/6942/3 "2024-06-18T16:38:14Z")

</div>

There also is a `-f json` option to output json instead of text.

---

<div class="post-metadata">

**Author:** ![Blacksmoke16](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/blacksmoke16/32/1241_2.png) [@Blacksmoke16](https://forum.crystal-lang.org/u/Blacksmoke16)\
**Post date:** [June 18, 2024, 4:52pm UTC](https://forum.crystal-lang.org/t/parse-output-of-command-that-interpret-crystal-script/6942/4 "2024-06-18T16:52:39Z")

</div>

I tried that, but didn’t seem to make a difference in this case.

---

<div class="post-metadata">

**Author:** ![Ragmaanir](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/ragmaanir/32/1174_2.png) [@Ragmaanir](https://forum.crystal-lang.org/u/Ragmaanir)\
**Post date:** [June 18, 2024, 5:13pm UTC](https://forum.crystal-lang.org/t/parse-output-of-command-that-interpret-crystal-script/6942/5 "2024-06-18T17:13:30Z")

</div>

When i run `crystal run zzz.cr -f json`, where the file only contains `asd`, then i get:

```auto
[{"file":"[snip]/zzz.cr","line":3,"column":1,"size":3,"message":"undefined local variable or method 'asd' for top-level"}]

```

---

<div class="post-metadata">

**Author:** ![Blacksmoke16](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/blacksmoke16/32/1241_2.png) [@Blacksmoke16](https://forum.crystal-lang.org/u/Blacksmoke16)\
**Post date:** [June 18, 2024, 5:20pm UTC](https://forum.crystal-lang.org/t/parse-output-of-command-that-interpret-crystal-script/6942/6 "2024-06-18T17:20:41Z")

</div>

Ahh, seems the difference is it’ll be JSON if the error is a compile time error. If it’s a runtime exception, then it won’t be.

If @Fulgurance’s error is a compile time one, then this would be perfect! As it’s already in a consumable format. Otherwise if its a runtime error will have to parse that out somehow.

---

<div class="post-metadata">

**Author:** ![Fulgurance](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/fulgurance/32/1463_2.png) [@Fulgurance](https://forum.crystal-lang.org/u/Fulgurance)\
**Post date:** [June 18, 2024, 6:38pm UTC](https://forum.crystal-lang.org/t/parse-output-of-command-that-interpret-crystal-script/6942/7 "2024-06-18T18:38:03Z")

</div>

Actually it’s a compile time errot I need ! So it’s perfect . Thanks a lot guys !

---

<div class="post-metadata">

**Author:** ![Fulgurance](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/fulgurance/32/1463_2.png) [@Fulgurance](https://forum.crystal-lang.org/u/Fulgurance)\
**Post date:** [June 18, 2024, 7:26pm UTC](https://forum.crystal-lang.org/t/parse-output-of-command-that-interpret-crystal-script/6942/8 "2024-06-18T19:26:34Z")

</div>

So I did that test but I get an error:

```crystal
require "json"

class Output

        property path : String
        property line : Int32
        property column : Int32
        property size : Int32
        property message : String

        include JSON::Serializable

end

processResult = IO::Memory.new

process = Process.run( "crystal build error.cr -f json",
                        error: processResult,
                        #error: :inherit,
                        shell: true)

puts Output.from_json(processResult)

```

```bash
zohran@alienware-m17-r3:~/Downloads$ crystal test.cr 
Unhandled exception: Expected BeginObject but was EOF at line 1, column 1
  parsing Output at line 0, column 0 (JSON::SerializableError)
  from /usr/share/crystal/src/json/serialization.cr:182:7 in 'initialize:__pull_for_json_serializable'
  from test.cr:11:9 in 'new_from_json_pull_parser'
  from test.cr:11:9 in 'new'
  from /usr/share/crystal/src/json/from_json.cr:13:3 in 'from_json'
  from test.cr:22:6 in '__crystal_main'
  from /usr/share/crystal/src/crystal/main.cr:129:5 in 'main_user_code'
  from /usr/share/crystal/src/crystal/main.cr:115:7 in 'main'
  from /usr/share/crystal/src/crystal/main.cr:141:3 in 'main'
  from /lib64/libc.so.6 in '??'
  from /lib64/libc.so.6 in '__libc_start_main'
  from /home/zohran/.cache/crystal/crystal-run-test.tmp in '_start'
  from ???
Caused by: Expected BeginObject but was EOF at line 1, column 1 (JSON::ParseException)
  from /usr/share/crystal/src/json/pull_parser.cr:705:5 in 'raise'
  from /usr/share/crystal/src/json/pull_parser.cr:696:5 in 'expect_kind'
  from /usr/share/crystal/src/json/pull_parser.cr:167:5 in 'read_begin_object'
  from /usr/share/crystal/src/json/serialization.cr:182:7 in 'initialize:__pull_for_json_serializable'
  from test.cr:11:9 in 'new_from_json_pull_parser'
  from test.cr:11:9 in 'new'
  from /usr/share/crystal/src/json/from_json.cr:13:3 in 'from_json'
  from test.cr:22:6 in '__crystal_main'
  from /usr/share/crystal/src/crystal/main.cr:129:5 in 'main_user_code'
  from /usr/share/crystal/src/crystal/main.cr:115:7 in 'main'
  from /usr/share/crystal/src/crystal/main.cr:141:3 in 'main'
  from /lib64/libc.so.6 in '??'
  from /lib64/libc.so.6 in '__libc_start_main'
  from /home/zohran/.cache/crystal/crystal-run-test.tmp in '_start'
  from ???

```

---

<div class="post-metadata">

**Author:** ![Blacksmoke16](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/blacksmoke16/32/1241_2.png) [@Blacksmoke16](https://forum.crystal-lang.org/u/Blacksmoke16)\
**Post date:** [June 18, 2024, 7:30pm UTC](https://forum.crystal-lang.org/t/parse-output-of-command-that-interpret-crystal-script/6942/9 "2024-06-18T19:30:23Z")

</div>

Few issues:

1. You need to rewind your `IO::Memory` before trying to read from it
2. The result is a `Array(Output)`, not just a single `Output`
3. The one property is called `file`, not `path`
4. Given the data is immutable, might be better to use a `struct` with `getter` instead of a `class` with `property`.

---

<div class="post-metadata">

**Author:** ![Fulgurance](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/fulgurance/32/1463_2.png) [@Fulgurance](https://forum.crystal-lang.org/u/Fulgurance)\
**Post date:** [June 18, 2024, 7:38pm UTC](https://forum.crystal-lang.org/t/parse-output-of-command-that-interpret-crystal-script/6942/11 "2024-06-18T19:38:17Z")

</div>

Okay got it, as usual, thanks a lot **Blacksmoke16**!

---

<div class="post-metadata">

**Author:** ![Fulgurance](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/fulgurance/32/1463_2.png) [@Fulgurance](https://forum.crystal-lang.org/u/Fulgurance)\
**Post date:** [June 19, 2024, 9:15pm UTC](https://forum.crystal-lang.org/t/parse-output-of-command-that-interpret-crystal-script/6942/12 "2024-06-19T21:15:40Z")

</div>

I have one last question because I am facing a problem, is it normal sometime the field size of the json output return **null** instead of a Int ???

---

<div class="post-metadata">

**Author:** ![Blacksmoke16](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/blacksmoke16/32/1241_2.png) [@Blacksmoke16](https://forum.crystal-lang.org/u/Blacksmoke16)\
**Post date:** [June 19, 2024, 9:35pm UTC](https://forum.crystal-lang.org/t/parse-output-of-command-that-interpret-crystal-script/6942/13 "2024-06-19T21:35:17Z")

</div>

It’s nilable in the compiler, so guess so.

---

<div class="post-metadata">

**Author:** ![Fulgurance](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/fulgurance/32/1463_2.png) [@Fulgurance](https://forum.crystal-lang.org/u/Fulgurance)\
**Post date:** [June 19, 2024, 9:35pm UTC](https://forum.crystal-lang.org/t/parse-output-of-command-that-interpret-crystal-script/6942/14 "2024-06-19T21:35:57Z")

</div>

Okay so I will code something to manage that

---

<div class="post-metadata">

**Author:** ![Blacksmoke16](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/blacksmoke16/32/1241_2.png) [@Blacksmoke16](https://forum.crystal-lang.org/u/Blacksmoke16)\
**Post date:** [June 19, 2024, 9:37pm UTC](https://forum.crystal-lang.org/t/parse-output-of-command-that-interpret-crystal-script/6942/15 "2024-06-19T21:37:36Z")

</div>

Not sure what you mean by “code something to manage that”, you just need to make that field nilable too. E.g. `getter size : Int32?`

---

<div class="post-metadata">

**Author:** ![Fulgurance](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/fulgurance/32/1463_2.png) [@Fulgurance](https://forum.crystal-lang.org/u/Fulgurance)\
**Post date:** [June 19, 2024, 9:49pm UTC](https://forum.crystal-lang.org/t/parse-output-of-command-that-interpret-crystal-script/6942/16 "2024-06-19T21:49:48Z")

</div>

Yeah it’s what I mean 🙂

But I think probably instead I will perform a gsub to ensure always that entry return a int. I don’t like to have variable with different types.

---

<div class="post-metadata">

**Author:** ![Blacksmoke16](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/blacksmoke16/32/1241_2.png) [@Blacksmoke16](https://forum.crystal-lang.org/u/Blacksmoke16)\
**Post date:** [June 19, 2024, 9:52pm UTC](https://forum.crystal-lang.org/t/parse-output-of-command-that-interpret-crystal-script/6942/17 "2024-06-19T21:52:01Z")

</div>

Keep it not nilable, but give it a default value of `0` or something then.
