I have earlier used Python for doing pretty output of JSON data like this:
python -mjson.tool input.json
I wanted to get similar output using Ruby. I am doing it like this:
ruby -rrubygems -e 'require "json"; ARGV.each { |f| print JSON.pretty_generate(JSON.load(File.open(f))) }' input.json
This is a lot for a small shell command. Can you suggest a better way?
You can shorten your script:
# ruby 1.9.2
ruby -rjson -e 'ARGF.each(nil) {|f| puts JSON.pretty_generate(JSON.parse(f)) }' file1 file2
# ruby 1.8.7
ruby -rubygems -e 'require "json"; ARGF.each(nil) {|f| puts JSON.pretty_generate(JSON.parse(f)) }' file1 file2
ARGF is a stream designed for use in scripts that process files given
as command-line arguments or passed in via STDIN.
I pass nil to ARGF#each method to split ARGF by files, not by lines (default behavior of #each).
There is a gem colorful_json which does exactly that.
You can also use the awesome_print gem.
Install it with: gem install awesome_print
Create a Bash function which will act as a shortcut
function jcurl { curl -s $* | ruby -rawesome_print -rjson -e 'ap JSON.parse(STDIN.read)'; }; export -f jcurl
Use your function to get pretty JSON in your Linux terminal:
jcurl http://127.0.0.1:3000/persons/1.json
Related
I have a file.csv:
value1,value2
that I convert to JSON using the following command:
# adding headers on the fly
echo 'key1,key2' |
ruby -rcsv -rjson -e 'puts CSV.new(ARGF,headers:true).map(&:to_hash).to_json' - file.csv
The output should be:
[{"key1":"value1","key2":"value2"}]
Which is the case with ruby-2.0 and 2.3, but with ruby-2.7, the output is:
[]
Further debugging showed that ruby-2.7 CSV lib doesn't handle ARGF well, it stops the reading after the first file in ARGF (stdin in my case).
Are newer Ruby versions also affected by this issue? Is there a more portable way to do the same magic?
I was able to reproduce this problem. It seems like the ARGF object is behaving the same way in both Ruby 2.5 and Ruby 2.7 though. Both versions give me this output:
$ echo 'key1,key2' | ruby -rcsv -rjson -e 'p ARGF.read; p ARGF.read; p ARGF.read' - file.csv
"key1,key2\n123,345\n"
nil
nil
However, there must be something weird about what the CSV library is doing that make your use case stop working.
Anyway, instead of counting on Ruby's ARGF and CSV libraries to concatenate the standard input with file.csv, you can just concatenate those two things using your shell instead, and it will work:
( echo 'key1,key2'; cat file.csv ) | ruby -rcsv -e 'puts CSV(ARGF,headers:true).map(&:to_hash)'
or
ruby -rcsv -e 'puts CSV(ARGF,headers:true).map(&:to_hash)' <( echo 'key1,key2'; cat file.csv )
Below you see my input file. Why does it output hash refs and not put the input without the ---?
$ cat a
---
Main:
aaah: Administrator
aacp: Administrator
a868: User
1585: User
5053: User
5423: User
/tmp$
$ ruby -pe 'gsub("---\n", '')' a
#<Enumerator:0x00005e335d1d08>#<Enumerator:0x00005e335d1b78>#<Enumerator:0x00005e335d1a38>#<Enumerator:0x00005e335d1920>#<Enumerator:0x00005e335d1808>#<Enumerator:0x00005e335d16f0>#<Enumerator:0x00005e335d15d8>#<Enumerator:0x00005e335d14c0>#<Enumerator:0x00005e335d13a8>#<Enumerator:0x00005e335d1290>
Your command needs the correct quotations.
Should look something like this:
$ ruby -pe 'gsub("---\n", "")' a
or
$ ruby -pe "gsub('---\n', '')" a
I have a .gz file in a folder called SequenceScripts.
I would like to unzip it and then run a ruby script on it which reformats it and puts it in a text file.
The ruby script is in the same folder.
I am doing this using Terminal on a mac.
The command I am using is:
gzcat tbb.fq.gz | ./reformat_sequence_data.rb > SLX-8691.ART03.txt
The response I am getting is: env: ruby\r: No such file or directory
The ruby script starts with:
#!/usr/bin/env ruby
There are no carriage returns in the script (checked with hidden characters visible).
When I run ruby -v from the command line I get: ruby 2.0.0p247 (2013-06-27 revision 41674) [universal.x86_64-darwin13]
I have no idea whats going on but I suspect the extra carriage return may have something to do with it but I dont know why its there. Can anyone help?
I suggest that you just run dos2unix or sed on it anyway:
dos2unix ./reformat_sequence_data.rb
sed -i 's|\r||' ./reformat_sequence_data.rb
If your file has \r (0D), lines will show with this command:
hexdump -C < ./reformat_sequence_data.rb | grep -w 0d
When using ruby -pi.xxx -e '$stdout.print $_' ./some_file.txt ruby is going to write into the file some_file.txt and I will end up having every text line twice in my file.
How can I redirect the input to end up in the console and not in my file?
From the Ruby man page:
-i extension
Specifies in-place-edit mode. The extension, if specified, is added to old file name
to make a backup copy.
In-place edit mode means that the output of the program is written to the original file instead of $stdout. To change this back to printing to stdout, simply leave out the -i flag, i.e.
ruby -pe '$stdout.print $_' ./some_file.txt
Some side notes:
$stdout.print $_ does exactly the same as print $_
I hope your example is not actual code, because it doesn't make very clear what it is supposed to achieve. To double the lines in a file I would rather write either ruby -ne 'puts $_ * 2' ./some_file.txt or ruby -pe '$_ *= 2' ./some_file.txt although I think the first one is clearer.
Say I was typing something in my terminal like:
ls | grep phrase
and after doing so I realize I want to delete all these files.
I want to use Ruby to do so, but can't quite figure out what to pass into it.
ls | grep phrase | ruby -e "what do I put in here to go through each line by line?"
Use this as a starting point:
ls ~ | ruby -ne 'print $_ if $_[/^D/]'
Which returns:
Desktop
Documents
Downloads
Dropbox
The -n flag means "loop over all incoming lines" and stores them in the "default" variable $_. We don't see that variable used much, partly as a knee-jerk reaction to Perl's overuse of it, but it has its useful moments in Rubydom.
These are the commonly used flags:
-e 'command' one line of script. Several -e's allowed. Omit [programfile]
-n assume 'while gets(); ... end' loop around your script
-p assume loop like -n but print line also like sed
ARGF will save your bacon.
ls | grep phrase | ruby -e "ARGF.read.each_line { |file| puts file }"
=> phrase_file
file_phrase
stuff_in_front_of_phrase
phrase_stuff_behind
ARGF is an array that stores whatever you passed into your (in this case command-line) script.
You can read more about ARGF here:
http://www.ruby-doc.org/core-1.9.3/ARGF.html
For more uses check out this talk on Ruby Forum:
http://www.ruby-forum.com/topic/85528