├── example_files
├── dept.txt
├── f1.txt
├── t2.txt
├── f2.txt
├── fruits.txt
├── dept_mark.txt
├── dept_name.txt
├── repl.txt
├── items.txt
├── colors.txt
├── colors_1.txt
├── greeting.txt
├── colors_2.txt
├── eqns.txt
├── f3.txt
├── newline.csv
├── search.txt
├── t1.txt
├── paths.txt
├── purchases.txt
├── table.txt
├── word_anchors.txt
├── marks.txt
├── report.log
├── duplicates.txt
├── broken.txt
├── uniform.txt
├── para.txt
├── ip.txt
├── context.txt
├── sample.json
└── sample.xml
├── exercises
├── names.txt
├── match.txt
├── search_terms.txt
├── text.txt
├── varying_fields.txt
├── split.txt
├── words.txt
├── quoted.txt
├── match_words.txt
├── secrets.txt
├── brackets.txt
├── copyright.txt
├── criteria.txt
├── hex.txt
├── fw.txt
├── table.txt
├── ip.txt
├── fields.txt
├── idx.txt
├── jumbled.txt
├── lines.txt
├── multisort.csv
├── broken.txt
├── error.txt
├── scores.csv
├── mixed_fs.txt
├── twos.txt
├── para.txt
├── f1.txt
├── result.csv
├── sample.txt
├── concat.txt
├── ruby.md
├── expected.md
├── oops.txt
├── Exercises.md
└── Exercise_solutions.md
├── images
├── ruby_oneliners_ls.png
├── warning.svg
└── info.svg
├── sample_chapters
└── ruby_oneliners_sample.pdf
├── LICENSE
├── code_snippets
├── Dealing_with_duplicates.sh
├── Multiple_file_input.sh
├── Oneliner_introduction.sh
├── Record_separators.sh
├── Two_file_processing.sh
├── Processing_structured_data.sh
├── Processing_multiple_records.sh
├── Line_processing.sh
└── Field_separators.sh
├── Version_changes.md
└── README.md
/example_files/dept.txt:
--------------------------------------------------------------------------------
1 | CSE
2 | ECE
3 |
--------------------------------------------------------------------------------
/example_files/f1.txt:
--------------------------------------------------------------------------------
1 | I ate 3 apples
2 |
--------------------------------------------------------------------------------
/exercises/names.txt:
--------------------------------------------------------------------------------
1 | Lin
2 | Cy
3 | Ith
4 |
--------------------------------------------------------------------------------
/example_files/t2.txt:
--------------------------------------------------------------------------------
1 | worse than ever
2 | too bad
3 |
--------------------------------------------------------------------------------
/exercises/match.txt:
--------------------------------------------------------------------------------
1 | print+this
2 | but not that
3 |
--------------------------------------------------------------------------------
/example_files/f2.txt:
--------------------------------------------------------------------------------
1 | I bought two balls and 3 bats
2 |
--------------------------------------------------------------------------------
/example_files/fruits.txt:
--------------------------------------------------------------------------------
1 | banana
2 | papaya
3 | mango
4 |
--------------------------------------------------------------------------------
/example_files/dept_mark.txt:
--------------------------------------------------------------------------------
1 | ECE 70
2 | EEE 65
3 | CSE 80
4 |
--------------------------------------------------------------------------------
/example_files/dept_name.txt:
--------------------------------------------------------------------------------
1 | EEE Moi
2 | CSE Amy
3 | ECE Raj
4 |
--------------------------------------------------------------------------------
/example_files/repl.txt:
--------------------------------------------------------------------------------
1 | 2$1$&3\0x\\yz
2 | wise ice go goa
3 |
--------------------------------------------------------------------------------
/example_files/items.txt:
--------------------------------------------------------------------------------
1 | apple fig banana
2 | 50 10 200
3 |
--------------------------------------------------------------------------------
/exercises/search_terms.txt:
--------------------------------------------------------------------------------
1 | hello
2 | row
3 | you
4 | is
5 | at
6 |
--------------------------------------------------------------------------------
/exercises/text.txt:
--------------------------------------------------------------------------------
1 | can ran want plant
2 | tin fin fit mine line
3 |
--------------------------------------------------------------------------------
/example_files/colors.txt:
--------------------------------------------------------------------------------
1 | deep blue
2 | light orange
3 | blue delight
4 |
--------------------------------------------------------------------------------
/example_files/colors_1.txt:
--------------------------------------------------------------------------------
1 | teal
2 | light blue
3 | green
4 | yellow
5 |
--------------------------------------------------------------------------------
/example_files/greeting.txt:
--------------------------------------------------------------------------------
1 | Hi there
2 | Have a nice day
3 | Good bye
4 |
--------------------------------------------------------------------------------
/exercises/varying_fields.txt:
--------------------------------------------------------------------------------
1 | hi,bye,there,was,here,to
2 | 1,2,3,4,5
3 |
--------------------------------------------------------------------------------
/example_files/colors_2.txt:
--------------------------------------------------------------------------------
1 | light blue
2 | black
3 | dark green
4 | yellow
5 |
--------------------------------------------------------------------------------
/exercises/split.txt:
--------------------------------------------------------------------------------
1 | apple,1:2:5,mango
2 | wry,4,look
3 | pencil,3:8,paper
4 |
--------------------------------------------------------------------------------
/exercises/words.txt:
--------------------------------------------------------------------------------
1 | bot
2 | art
3 | are
4 | boat
5 | toe
6 | flee
7 | reed
8 |
--------------------------------------------------------------------------------
/example_files/eqns.txt:
--------------------------------------------------------------------------------
1 | a=b,a-b=c,c*d
2 | a+b,pi=3.14,5e12
3 | i*(t+9-g)/8,4-a+b
4 |
--------------------------------------------------------------------------------
/example_files/f3.txt:
--------------------------------------------------------------------------------
1 | Name Physics Maths
2 | Moe 76 82
3 | Raj 56 64
4 |
--------------------------------------------------------------------------------
/example_files/newline.csv:
--------------------------------------------------------------------------------
1 | apple,"1
2 | 2
3 | 3",good
4 | guava,"32
5 | 54",nice
6 |
--------------------------------------------------------------------------------
/example_files/search.txt:
--------------------------------------------------------------------------------
1 | brown bread mat hair 42
2 | blue cake mug shirt -7
3 |
--------------------------------------------------------------------------------
/exercises/quoted.txt:
--------------------------------------------------------------------------------
1 | 1 "grape" and "mango" and "guava"
2 | ("c 1""d""a-2""b")
3 |
--------------------------------------------------------------------------------
/example_files/t1.txt:
--------------------------------------------------------------------------------
1 | have a nice day
2 | bad morning
3 | what a pleasant evening
4 |
--------------------------------------------------------------------------------
/exercises/match_words.txt:
--------------------------------------------------------------------------------
1 | %whole(Hello)--{doubt}==ado==
2 | just,\joint*,concession<=nice
3 |
--------------------------------------------------------------------------------
/exercises/secrets.txt:
--------------------------------------------------------------------------------
1 | stag area row tick
2 | deaf chi rate tall glad
3 | Bi tac toe - 42
4 |
--------------------------------------------------------------------------------
/exercises/brackets.txt:
--------------------------------------------------------------------------------
1 | foo blah blah(ice) 123 xyz$
2 | (almond-pista) choco
3 | yo )yoyo( yo
4 |
--------------------------------------------------------------------------------
/example_files/paths.txt:
--------------------------------------------------------------------------------
1 | /home/joe/report.log
2 | /home/ram/power.log
3 | /home/rambo/errors.log
4 |
--------------------------------------------------------------------------------
/exercises/copyright.txt:
--------------------------------------------------------------------------------
1 | bla bla 2015 bla
2 | blah 2018 blah
3 | bla bla bla
4 | copyright: 2018
5 |
--------------------------------------------------------------------------------
/exercises/criteria.txt:
--------------------------------------------------------------------------------
1 | Amy maths
2 | John chemistry
3 | John physics
4 | Ravi chemistry
5 | Yui maths
6 |
--------------------------------------------------------------------------------
/exercises/hex.txt:
--------------------------------------------------------------------------------
1 | start: 0xA0, func1: 0xA0
2 | end: 0xFF, func2: 0xB0
3 | restart: 0xA010, func3: 0x7F
4 |
--------------------------------------------------------------------------------
/exercises/fw.txt:
--------------------------------------------------------------------------------
1 | 1.3 rs 90 0.134563
2 | 3.8 6
3 | 5.2 ye 8.2387
4 | 4.2 kt 32 45.1
5 |
--------------------------------------------------------------------------------
/exercises/table.txt:
--------------------------------------------------------------------------------
1 | brown bread mat hair 42
2 | blue cake mug shirt -7
3 | yellow banana window shoes 3.14
4 |
--------------------------------------------------------------------------------
/example_files/purchases.txt:
--------------------------------------------------------------------------------
1 | coffee
2 | tea
3 | washing powder
4 | coffee
5 | toothpaste
6 | tea
7 | soap
8 | tea
9 |
--------------------------------------------------------------------------------
/example_files/table.txt:
--------------------------------------------------------------------------------
1 | brown bread mat hair 42
2 | blue cake mug shirt -7
3 | yellow banana window shoes 3.14
4 |
--------------------------------------------------------------------------------
/exercises/ip.txt:
--------------------------------------------------------------------------------
1 | Hello World
2 | How are you
3 | This game is good
4 | Today is sunny
5 | 12345
6 | You are funny
7 |
--------------------------------------------------------------------------------
/example_files/word_anchors.txt:
--------------------------------------------------------------------------------
1 | sub par
2 | spar
3 | apparent effort
4 | two spare computers
5 | cart part tart mart
6 |
--------------------------------------------------------------------------------
/exercises/fields.txt:
--------------------------------------------------------------------------------
1 | 42:cat
2 | twelve:a2b
3 | we:be:he:0:a:b:bother
4 | apple:banana-42:cherry:
5 | dragon:unicorn:centaur
6 |
--------------------------------------------------------------------------------
/images/ruby_oneliners_ls.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/learnbyexample/learn_ruby_oneliners/HEAD/images/ruby_oneliners_ls.png
--------------------------------------------------------------------------------
/exercises/idx.txt:
--------------------------------------------------------------------------------
1 | match after the last newline character
2 | and then you want to test
3 | this is good bye then
4 | you were there to see?
5 |
--------------------------------------------------------------------------------
/exercises/jumbled.txt:
--------------------------------------------------------------------------------
1 | overcoats;furrowing-typeface%pewter##hobby
2 | wavering:concession/woof\retailer
3 | joint[]seer{intuition}titanic
4 |
--------------------------------------------------------------------------------
/exercises/lines.txt:
--------------------------------------------------------------------------------
1 | Go There
2 | come on
3 | go there
4 | ---
5 | 2 apples and 5 mangoes
6 | come on!
7 | ---
8 | 2 Apples
9 | COME ON
10 |
--------------------------------------------------------------------------------
/example_files/marks.txt:
--------------------------------------------------------------------------------
1 | Dept Name Marks
2 | ECE Raj 53
3 | ECE Joel 72
4 | EEE Moi 68
5 | CSE Surya 81
6 | EEE Tia 59
7 | ECE Om 92
8 | CSE Amy 67
9 |
--------------------------------------------------------------------------------
/exercises/multisort.csv:
--------------------------------------------------------------------------------
1 | papaya,2
2 | apple,4:5:2
3 | mango,100
4 | dark:chocolate,12:32
5 | cherry,1:2:1:4:2:1
6 | almond,3:14:6:28
7 | banana,23:8
8 |
--------------------------------------------------------------------------------
/sample_chapters/ruby_oneliners_sample.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/learnbyexample/learn_ruby_oneliners/HEAD/sample_chapters/ruby_oneliners_sample.pdf
--------------------------------------------------------------------------------
/exercises/broken.txt:
--------------------------------------------------------------------------------
1 | top
2 | 3.14
3 | bottom
4 | ---
5 | top
6 | 1234567890
7 | bottom
8 | top
9 | Hi there
10 | Have a nice day
11 | Good bye
12 |
--------------------------------------------------------------------------------
/exercises/error.txt:
--------------------------------------------------------------------------------
1 | print+this
2 | but not that or this
3 | print+this
4 | but not that
5 | if print+this
6 | but not that
7 | print+this
8 | but not that
9 |
--------------------------------------------------------------------------------
/exercises/scores.csv:
--------------------------------------------------------------------------------
1 | Name,Maths,Physics,Chemistry
2 | Blue,67,46,99
3 | Lin,78,83,80
4 | Er,56,79,92
5 | Cy,97,98,95
6 | Ort,68,72,66
7 | Ith,100,100,100
8 |
--------------------------------------------------------------------------------
/exercises/mixed_fs.txt:
--------------------------------------------------------------------------------
1 | rose lily jasmine tulip
2 | pink blue white yellow
3 | car,mat,ball,basket
4 | light green,brown,black,purple
5 | apple,banana,cherry
6 |
--------------------------------------------------------------------------------
/example_files/report.log:
--------------------------------------------------------------------------------
1 | blah blah Error: second record starts
2 | something went wrong
3 | some more details Error: third record
4 | details about what went wrong
5 |
--------------------------------------------------------------------------------
/exercises/twos.txt:
--------------------------------------------------------------------------------
1 | hehe haha
2 | door floor
3 | haha hehe
4 | 6;8 3-4
5 | true blue
6 | hehe bebe
7 | floor door
8 | 3-4 6;8
9 | tru eblue
10 | haha hehe
11 |
--------------------------------------------------------------------------------
/exercises/para.txt:
--------------------------------------------------------------------------------
1 | good start
2 | Start working on that
3 | project you always wanted
4 | to, do not let it end
5 | hi there
6 | start and try to
7 | finish the End
8 | bye
9 |
--------------------------------------------------------------------------------
/exercises/f1.txt:
--------------------------------------------------------------------------------
1 |
2 | hello
3 |
4 |
5 |
6 |
7 | world
8 |
9 | apple
10 | banana
11 | cherry
12 |
13 |
14 | tea coffee
15 | chocolate
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/exercises/result.csv:
--------------------------------------------------------------------------------
1 | Amy,maths,89
2 | Amy,physics,75
3 | Joe,maths,79
4 | John,chemistry,77
5 | John,physics,91
6 | Moe,maths,81
7 | Ravi,physics,84
8 | Ravi,chemistry,70
9 | Yui,maths,92
10 |
--------------------------------------------------------------------------------
/example_files/duplicates.txt:
--------------------------------------------------------------------------------
1 | brown,toy,bread,42
2 | dark red,ruby,rose,111
3 | blue,ruby,water,333
4 | dark red,sky,rose,555
5 | yellow,toy,flower,333
6 | white,sky,bread,111
7 | light red,purse,rose,333
8 |
--------------------------------------------------------------------------------
/example_files/broken.txt:
--------------------------------------------------------------------------------
1 | qqqqqqqqqqqqqqqq
2 | error 1
3 | hi
4 | error 2
5 | 1234
6 | 6789
7 | state 1
8 | bye
9 | state 2
10 | error 3
11 | xyz
12 | error 4
13 | abcd
14 | state 3
15 | zzzzzzzzzzzzzzzz
16 |
--------------------------------------------------------------------------------
/example_files/uniform.txt:
--------------------------------------------------------------------------------
1 | mango
2 | icecream
3 | --start 1--
4 | 1234
5 | 6789
6 | **end 1**
7 | how are you
8 | have a nice day
9 | --start 2--
10 | a
11 | b
12 | c
13 | **end 2**
14 | par,far,mar,tar
15 |
--------------------------------------------------------------------------------
/example_files/para.txt:
--------------------------------------------------------------------------------
1 | Hello World
2 |
3 | Hi there
4 | How are you
5 |
6 | Just do-it
7 | Believe it
8 |
9 | banana
10 | papaya
11 | mango
12 |
13 | Much ado about nothing
14 | He he he
15 | Adios amigo
16 |
--------------------------------------------------------------------------------
/exercises/sample.txt:
--------------------------------------------------------------------------------
1 | Hello World
2 |
3 | Good day
4 | How are you
5 |
6 | Just do-it
7 | Believe it
8 |
9 | Today is sunny
10 | Not a bit funny
11 | No doubt you like it too
12 |
13 | Much ado about nothing
14 | He he he
15 |
--------------------------------------------------------------------------------
/example_files/ip.txt:
--------------------------------------------------------------------------------
1 | it is a warm and cozy day
2 | listen to what I say
3 | go play in the park
4 | come back before the sky turns dark
5 |
6 | There are so many delights to cherish
7 | Apple, Banana and Cherry
8 | Bread, Butter and Jelly
9 | Try them all before you perish
10 |
--------------------------------------------------------------------------------
/example_files/context.txt:
--------------------------------------------------------------------------------
1 | blue
2 | toy
3 | flower
4 | sand stone
5 | light blue
6 | flower
7 | sky
8 | water
9 | language
10 | english
11 | hindi
12 | spanish
13 | tamil
14 | programming language
15 | python
16 | kotlin
17 | ruby
18 |
--------------------------------------------------------------------------------
/exercises/concat.txt:
--------------------------------------------------------------------------------
1 | %%% addr.txt
2 | How are you
3 | This game is good
4 | Today %%% is sunny
5 | %%% broken.txt
6 | top %%%
7 | 1234567890
8 | bottom
9 | %%% sample.txt
10 | Just %%% do-it
11 | Believe it
12 | %%% mixed_fs.txt
13 | pink blue white yellow
14 | car,mat,ball,basket
15 |
--------------------------------------------------------------------------------
/example_files/sample.json:
--------------------------------------------------------------------------------
1 | {
2 | "fruit": "apple",
3 | "blue": ["toy", "flower", "sand stone"],
4 | "light blue": ["flower", "sky", "water"],
5 | "language": {
6 | "natural": ["english", "hindi", "spanish"],
7 | "programming": ["python", "kotlin", "ruby"]
8 | },
9 | "physics": 84
10 | }
11 |
--------------------------------------------------------------------------------
/example_files/sample.xml:
--------------------------------------------------------------------------------
1 |
2 | Hi there. How are you?
3 | I am good.
4 |
5 | flower
6 | sand stone
7 | sky
8 | water
9 |
10 |
11 |
--------------------------------------------------------------------------------
/exercises/ruby.md:
--------------------------------------------------------------------------------
1 | # Introduction
2 |
3 | REPL is a good way to learn RUBY for beginners.
4 |
5 | ```ruby
6 | >> 3 + 7
7 | => 10
8 | >> 22 / 7
9 | => 3
10 | >> 22.0 / 7
11 | => 3.142857142857143
12 | ```
13 |
14 | ## String methods
15 |
16 | ruby comes loaded with awesome methods. Enjoy learning RuBy.
17 |
18 | ```ruby
19 | >> 'ruby'.capitalize
20 | => "Ruby"
21 |
22 | >> ' comma '.strip
23 | => "comma"
24 | ```
25 |
26 |
--------------------------------------------------------------------------------
/exercises/expected.md:
--------------------------------------------------------------------------------
1 | # Introduction
2 |
3 | REPL is a good way to learn Ruby for beginners.
4 |
5 | ```ruby
6 | >> 3 + 7
7 | => 10
8 | >> 22 / 7
9 | => 3
10 | >> 22.0 / 7
11 | => 3.142857142857143
12 | ```
13 |
14 | ## String methods
15 |
16 | Ruby comes loaded with awesome methods. Enjoy learning Ruby.
17 |
18 | ```ruby
19 | >> 'ruby'.capitalize
20 | => "Ruby"
21 |
22 | >> ' comma '.strip
23 | => "comma"
24 | ```
25 |
26 |
--------------------------------------------------------------------------------
/exercises/oops.txt:
--------------------------------------------------------------------------------
1 | hello
2 | row
3 | you
4 | is
5 | at
6 | hello
7 | row
8 | you
9 | is
10 | at
11 | hello
12 | row
13 | you
14 | is
15 | at
16 | hello
17 | row
18 | you
19 | is
20 | at
21 | hello
22 | row
23 | you
24 | is
25 | at
26 | hello
27 | row
28 | you
29 | is
30 | at
31 | hello
32 | row
33 | you
34 | is
35 | at
36 | hello
37 | row
38 | you
39 | is
40 | at
41 | hello
42 | row
43 | you
44 | is
45 | at
46 | hello
47 | row
48 | you
49 | is
50 | at
51 | hello
52 | row
53 | you
54 | is
55 | at
56 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2024 Sundeep Agarwal
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/code_snippets/Dealing_with_duplicates.sh:
--------------------------------------------------------------------------------
1 | ## Whole line duplicates
2 |
3 | cat purchases.txt
4 |
5 | ruby -e 'puts readlines.uniq' purchases.txt
6 |
7 | ruby -rset -ne 'BEGIN{s=Set.new}; print if s.add?($_)' purchases.txt
8 |
9 | ## Column wise duplicates
10 |
11 | cat duplicates.txt
12 |
13 | ruby -rset -F, -ane 'BEGIN{s=Set.new}; print if s.add?($F[-1])' duplicates.txt
14 |
15 | ruby -rset -F, -ane 'BEGIN{s=Set.new};
16 | print if s.add?($F.values_at(0,2))' duplicates.txt
17 |
18 | ## Duplicate count
19 |
20 | ruby -F, -ane 'BEGIN{h=Hash.new(0)};
21 | print if (h[$F[1]]+=1)==2' duplicates.txt
22 |
23 | ruby -F, -ane 'BEGIN{h=Hash.new(0)};
24 | print if (h[$F[-1]]+=1)==3' duplicates.txt
25 |
26 | tac duplicates.txt | ruby -rset -F, -ane 'BEGIN{s=Set.new};
27 | print if s.add?($F[-1])' | tac
28 |
29 | ruby -F, -ane 'BEGIN{h=Hash.new(0)}; ARGV.size==1 ? h[$F[-1]]+=1 :
30 | h[$F[-1]]>1 && print' duplicates.txt duplicates.txt
31 |
32 | ruby -F, -ane 'BEGIN{h=Hash.new(0)}; ARGV.size==1 ? h[$F[-1]]+=1 :
33 | h[$F[-1]]>2 && print' duplicates.txt duplicates.txt
34 |
35 | ruby -F, -ane 'BEGIN{h=Hash.new(0)}; ARGV.size==1 ? h[$F[2]]+=1 :
36 | h[$F[2]]==1 && print' duplicates.txt duplicates.txt
37 |
38 |
--------------------------------------------------------------------------------
/code_snippets/Multiple_file_input.sh:
--------------------------------------------------------------------------------
1 | ## ARGV and ARGF
2 |
3 | ruby -e 'puts ARGV' f[1-3].txt greeting.txt
4 |
5 | ruby -ne 'puts "#{ARGV.size}: " + ARGV * ","' f[12].txt table.txt
6 |
7 | ruby -ne 'puts "--- #{ARGF.filename} ---" if $. == 1;
8 | print;
9 | ARGF.close if ARGF.eof' greeting.txt table.txt
10 |
11 | ruby -ne 'print if ARGF.eof' greeting.txt table.txt
12 |
13 | ruby -ne '(print; ARGF.close) if $.==2' greeting.txt table.txt
14 |
15 | ruby -pe 'ARGF.close if $.>=1' greeting.txt table.txt
16 |
17 | ruby -e 'puts gets' greeting.txt
18 |
19 | ruby -e 'puts gets, "---", ARGF.read' greeting.txt
20 |
21 | ruby -e 'puts readlines' greeting.txt
22 |
23 | ruby -e 'puts ARGF.readchar' greeting.txt
24 |
25 | ## STDIN
26 |
27 | printf 'apple\nmango\n' | ruby -e 'puts readline'
28 |
29 | printf 'apple\nmango\n' | ruby -e 'puts readline' greeting.txt
30 |
31 | printf 'apple\nmango\n' | ruby -e 'puts STDIN.readline' greeting.txt
32 |
33 | ## Skipping remaining contents per file
34 |
35 | ruby -ne '/\bba/ ? ARGF.close : print' ip.txt table.txt
36 |
37 | ruby -ne '(puts ARGF.filename; ARGF.close) if /I/' f[1-3].txt greeting.txt
38 |
39 | ruby -ne '$m1=true if /e\b/; $m2=true if /[bm]at/i;
40 | (puts ARGF.filename; $m1=$m2=false; ARGF.close; next) if $m1 && $m2;
41 | $m1=$m2=false if ARGF.eof' f[1-3].txt greeting.txt
42 |
43 |
--------------------------------------------------------------------------------
/Version_changes.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | ### 2.0
4 |
5 | * Command version updated to **Ruby 3.3.0**
6 | * Added more exercises
7 | * Long sections split into smaller ones
8 | * In general, many of the examples, exercises, solutions, descriptions and external links were updated/corrected
9 | * Updated Acknowledgements section
10 | * Code snippets related to info/warning sections will now appear as a single block
11 | * Book title changed to **Ruby One-Liners Guide**
12 | * New cover image
13 |
14 |
15 |
16 | ### 1.6
17 |
18 | * Corrected usage of substitution methods for fixed string replacement
19 | * Updated `ruby` version to **3.0.0**
20 | * Added example with `-l` usage when input has `\r\n` line endings
21 | * Miscellaneous changes like better description, fixed typos, etc
22 |
23 |
24 |
25 | ### 1.5
26 |
27 | * added `pngquant` and `svgcleaner` in Acknowledgements
28 | * added example for `-s` option
29 | * updated/added examples/exercises for `tr`, Flip-Flop operator, `sort`, `ARGF`, `STDIN`, etc
30 | * added example to show effect of `exit` within `BEGIN` and `END` blocks
31 | * added substitution examples for fixed string data
32 | * miscellaneous changes like better description, removing trailing whitespaces, fixed typos, etc
33 | * added section for multiline fixed string substitution
34 | * added section for adding entire contents of a file based on a condition
35 |
36 |
37 |
38 | ### 1.0
39 |
40 | * First version
41 |
--------------------------------------------------------------------------------
/images/warning.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/code_snippets/Oneliner_introduction.sh:
--------------------------------------------------------------------------------
1 | ## Executing Ruby code
2 |
3 | echo 'puts "Hello Ruby"' > hello.rb
4 |
5 | ruby hello.rb
6 |
7 | ruby -e 'puts "Hello Ruby"'
8 |
9 | ruby -e 'x=25; y=12; puts x**y'
10 |
11 | ruby -e 'x=25' -e 'y=12' -e 'puts x**y'
12 |
13 | ## Filtering
14 |
15 | printf 'gate\napple\nwhat\nkite\n'
16 |
17 | printf 'gate\napple\nwhat\nkite\n' | ruby -ne 'print if /at/'
18 |
19 | printf 'gate\napple\nwhat\nkite\n' | ruby -ne 'print if !/e/'
20 |
21 | cat table.txt
22 |
23 | ruby -ne 'puts $& if /\d+$/' table.txt
24 |
25 | ruby -ne 'puts $& if /(? out.txt")'
74 |
75 | cat out.txt
76 |
77 | ruby -e 'es=system("ls word_anchors.txt"); puts es'
78 |
79 | ruby -e 'system("ls word_anchors.txt"); puts $?'
80 |
81 | ruby -e 'system("ls xyz.txt"); puts $?'
82 |
83 | ruby -e 'words = `wc -w = d[$F[0]]' dept_mark.txt marks.txt
42 |
43 | ruby -lane 'BEGIN{g = %w[D C B A S]};
44 | $F.append($.==1 ? "Grade" : g[$F[-1].to_i/10 - 5]);
45 | print $F * "\t"' marks.txt
46 |
47 | ## gets
48 |
49 | ruby -pe 'BEGIN{m=3; n=2; n.times {$s = STDIN.gets}};
50 | $_ = $s if $. == m' 0' search.txt
58 |
59 | cat repl.txt
60 |
61 | ruby -0777 -ne 'ARGV.size==2 ? s=$_ : ARGV.size==1 ? r=$_ :
62 | print(gsub(s) {r})
63 | ' search.txt repl.txt table.txt
64 |
65 | ## Add file content conditionally
66 |
67 | ruby -pe 'BEGIN{r = STDIN.read}; $_ = r if /[ot]/'
--------------------------------------------------------------------------------
/code_snippets/Processing_structured_data.sh:
--------------------------------------------------------------------------------
1 | ## JSON
2 |
3 | s='{"greeting":"hi","marks":[78,62,93]}'
4 |
5 | echo "$s" | ruby -rjson -e 'ip = JSON.parse(ARGF.read);
6 | puts JSON.pretty_generate(ip)'
7 |
8 | type rq
9 |
10 | rq() { ruby -rjson -e 'ip = JSON.parse(ARGF.read);'"$@" ; }
11 |
12 | s='{"greeting":"hi","marks":[78,62,93]}'
13 |
14 | echo "$s" | rq 'puts ip["greeting"]'
15 |
16 | echo "$s" | rq 'print ip["marks"]' -l
17 |
18 | echo "$s" | rq 'ip["marks"][1] = 100; puts JSON.generate(ip)'
19 |
20 | cat sample.json
21 |
22 | rq 'ip.each {|k,v| puts "#{k}:#{v}" if !k.match?(/e/)}' sample.json
23 |
24 | rq 'ip["language"].each {|k,v| puts "#{k}:#{v}" if k.match?(/t/)}' sample.json
25 |
26 | ## CSV
27 |
28 | s='eagle,"fox,42",bee,frog\n1,2,3,4'
29 |
30 | printf '%b' "$s" | ruby -rcsv -le 'ip=CSV.new(ARGF.read); print ip.read'
31 |
32 | printf '%b' "$s" | ruby -rcsv -e 'ip=CSV.new(ARGF.read); puts ip.read[0][1]'
33 |
34 | cat newline.csv
35 |
36 | ruby -rcsv -le 'ip=CSV.read("newline.csv"); print ip'
37 |
38 | ruby -rcsv -e 'CSV.foreach("newline.csv"){ |row|
39 | puts row[2] if row[0]=~/pp/ }'
40 |
41 | ruby -rcsv -e 'CSV.foreach("marks.txt", :col_sep => "\t"){ |r|
42 | puts r * "," if r[0]=="ECE" }'
43 |
44 | ruby -rcsv -e 'CSV.foreach("marks.txt", :headers => true, :col_sep => "\t"){
45 | |r| puts r["Name"] }'
46 |
47 | ruby -rcsv -le 'CSV.foreach("marks.txt", :converters => :integer,
48 | :col_sep => "\t"){ print _1 }'
49 |
50 | ## XML and HTML
51 |
52 | cat sample.xml
53 |
54 | ruby -rnokogiri -e 'ip=Nokogiri.XML(ARGF);
55 | puts ip.xpath("//blue")' sample.xml
56 |
57 | ruby -rnokogiri -e 'ip=Nokogiri.XML(ARGF);
58 | puts ip.xpath("//blue").grep(/stone/)' sample.xml
59 |
60 | ruby -rnokogiri -e 'ip=Nokogiri.XML(ARGF);
61 | puts ip.at_xpath("//blue")' sample.xml
62 |
63 | ruby -rnokogiri -e 'ip=Nokogiri.XML(ARGF);
64 | puts ip.css("light-blue").map(&:text)' sample.xml
65 |
66 | ruby -rnokogiri -e 'ip=Nokogiri.XML(ARGF);
67 | puts ip.at_css("blue").text' sample.xml
68 |
69 | ruby -rnokogiri -e 'ip=Nokogiri.XML(ARGF);
70 | puts ip.xpath("//greeting/@type")' sample.xml
71 |
72 | ruby -rnokogiri -e 'ip=Nokogiri.XML(ARGF);
73 | puts ip.xpath("//greeting[@type=\"ask\"]").text' sample.xml
74 |
75 | s='https://learnbyexample.github.io/substitution-with-ripgrep/'
76 |
77 | url="$s" ruby -rnokogiri -ropen-uri -e 'ip=Nokogiri.HTML(URI.open(ENV["url"]));
78 | puts ip.css("@href")[5..7]'
79 |
80 |
--------------------------------------------------------------------------------
/code_snippets/Processing_multiple_records.sh:
--------------------------------------------------------------------------------
1 | ## Processing consecutive records
2 |
3 | ruby -ne 'puts $p, $_ if /you/ && $p=~/he/; $p = $_' para.txt
4 |
5 | ruby -ne 'puts $p if /you/ && $p=~/he/; $p = $_' para.txt
6 |
7 | ruby -ne 'print if /you/ && $p=~/he/; $p = $_' para.txt
8 |
9 | ## Context matching
10 |
11 | cat context.txt
12 |
13 | ruby -ne '$n=1 if /blue/; print if $n && $n>=0 && $n-=1' context.txt
14 |
15 | ruby -ne '$n=1 if /toy|flower/; print if $n && $n>=0 && $n-=1' context.txt
16 |
17 | ruby -ne 'print if $n && $n>0 && $n-=1; $n=2 if /language/' context.txt
18 |
19 | ruby -ne 'print if $n.to_i>0 && ($n-=1)==0; $n=3 if /language/' context.txt
20 |
21 | ruby -e 'ip=readlines; n=2; ip.each_with_index { |s, i|
22 | puts ip[i-n..i] if s.match?(/stone/) }' context.txt
23 |
24 | ruby -e 'ip=readlines; n=2; ip.each_with_index { |s, i|
25 | c=i-n; c=0 if c<0;
26 | puts ip[c..i] if s.match?(/toy/) }' context.txt
27 |
28 | ruby -e 'ip=readlines; n=2; ip.each_with_index { |s, i|
29 | c=i-n; c=0 if c<0;
30 | (print $s; puts ip[c..i]; $s="---\n") if s.match?(/toy|flower/) }
31 | ' context.txt
32 |
33 | ruby -e 'ip=readlines; n=2; ip.each_with_index { |s, i| c=i-n;
34 | puts ip[c] if c>=0 && s.match?(/language/) }' context.txt
35 |
36 | ruby -ne 'print $p2 if $.>2 && /toy|flower/; $p2=$p1; $p1=$_' context.txt
37 |
38 | tac context.txt | ruby -ne 'print if $n.to_i>0 && ($n-=1)==0;
39 | $n=2 if /language/' | tac
40 |
41 | ## Records bounded by distinct markers
42 |
43 | cat uniform.txt
44 |
45 | ruby -ne '$f=true if /start/; print if $f; $f=false if /end/' uniform.txt
46 |
47 | ruby -ne '$f=false if /end/; print "* ", $_ if $f;
48 | $f=true if /start/' uniform.txt
49 |
50 | ruby -ne '$f=true if /start/; $f=false if /end/; print if $f' uniform.txt
51 |
52 | ruby -ne 'print if $f; $f=true if /start/; $f=false if /end/' uniform.txt
53 |
54 | ruby -ne '$f=true if /start/; print if !$f; $f=false if /end/' uniform.txt
55 |
56 | ruby -ne '$f=false if /end/; print if !$f; $f=true if /start/' uniform.txt
57 |
58 | ruby -ne 'print if !$f; $f=true if /start/; $f=false if /end/' uniform.txt
59 |
60 | ruby -ne '$f=true if /start/; $f=false if /end/; print if !$f' uniform.txt
61 |
62 | ## Specific blocks
63 |
64 | ruby -ne '$f=true if /start/; print if $f; exit if /end/' uniform.txt
65 |
66 | ruby -ne 'exit if /end/; print if $f; $f=true if /start/' uniform.txt
67 |
68 | tac uniform.txt | ruby -ne '$f=true if /end/; print if $f; exit if /start/' | tac
69 |
70 | ruby -ne '($f=true; buf=$_; next) if /start/;
71 | buf << $_ if $f;
72 | $f=false if /end/;
73 | END{print buf}' uniform.txt
74 |
75 | seq 30 | ruby -ne 'BEGIN{n=2; c=0}; c+=1 if /4/; (print; exit if /6/) if c==n'
76 |
77 | seq 30 | ruby -ne 'BEGIN{n=1; c=0}; ($f=true; c+=1) if /4/;
78 | print if $f && c>n; $f=false if /6/'
79 |
80 | seq 30 | ruby -ne 'BEGIN{n=2; c=0}; ($f=true; c+=1) if /4/;
81 | print if $f && c!=n; $f=false if /6/'
82 |
83 | seq 30 | ruby -ne '($f=true; buf=$_; next) if /4/; buf << $_ if $f;
84 | ($f=false; print buf if buf.match?(/^15$/)) if /6/;'
85 |
86 | ## Broken blocks
87 |
88 | cat broken.txt
89 |
90 | ruby -ne '($f=true; buf=$_; next) if /error/;
91 | buf << $_ if $f;
92 | (print buf if $f; $f=false) if /state/' broken.txt
93 |
94 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Ruby One-Liners Guide
2 |
3 | Example based guide for text processing with Ruby from the command line. Visit https://youtu.be/nsWVepZruws for a short video about the book.
4 |
5 |
6 |
7 | The book also includes exercises to test your understanding, which are presented together as a single file in this repo — [Exercises.md](./exercises/Exercises.md).
8 |
9 | For solutions to the exercises, see [Exercise_solutions.md](./exercises/Exercise_solutions.md).
10 |
11 | See [Version_changes.md](./Version_changes.md) to keep track of changes made to the book.
12 |
13 |
14 |
15 | # E-book
16 |
17 | * You can purchase the pdf/epub versions of the book using these links:
18 | * https://learnbyexample.gumroad.com/l/ruby-oneliners
19 | * https://leanpub.com/ruby-oneliners
20 | * You can also get the book as part of these bundles:
21 | * **Ruby text processing** bundle from https://learnbyexample.gumroad.com/l/ruby-textprocessing or https://leanpub.com/b/ruby-textprocessing
22 | * **Magical one-liners** bundle from https://learnbyexample.gumroad.com/l/oneliners or https://leanpub.com/b/oneliners
23 | * **All books bundle** bundle from https://learnbyexample.gumroad.com/l/all-books
24 | * Includes all my programming books
25 | * See https://learnbyexample.github.io/books/ for a list of other books
26 |
27 | For a preview of the book, see [sample chapters](./sample_chapters/ruby_oneliners_sample.pdf).
28 |
29 | The book can also be [viewed as a single markdown file in this repo](./ruby_oneliners.md). See my blogpost on [generating pdfs from markdown using pandoc](https://learnbyexample.github.io/customizing-pandoc/) if you are interested in the ebook creation process.
30 |
31 | For the web version of the book, visit https://learnbyexample.github.io/learn_ruby_oneliners/
32 |
33 |
34 |
35 | # Testimonials
36 |
37 | >This Ruby one-liners cookbook is incredible. Pretty mind boggling all the stuff you can do.
38 | >
39 | > — [feedback on twitter](https://twitter.com/jbrancha/status/1506766118756786189)
40 |
41 |
42 |
43 | # Feedback
44 |
45 | ⚠️ ⚠️ Please DO NOT submit pull requests. Main reason being any modification requires changes in multiple places.
46 |
47 | I would highly appreciate it if you'd let me know how you felt about this book. It could be anything from a simple thank you, pointing out a typo, mistakes in code snippets, which aspects of the book worked for you (or didn't!) and so on. Reader feedback is essential and especially so for self-published authors.
48 |
49 | You can reach me via:
50 |
51 | * Issue Manager: [https://github.com/learnbyexample/learn_ruby_oneliners/issues](https://github.com/learnbyexample/learn_ruby_oneliners/issues)
52 | * E-mail: `echo 'bGVhcm5ieWV4YW1wbGUubmV0QGdtYWlsLmNvbQo=' | base64 --decode`
53 | * Twitter: [https://twitter.com/learn_byexample](https://twitter.com/learn_byexample)
54 |
55 |
56 |
57 | # Table of Contents
58 |
59 | 1) Preface
60 | 2) One-liner introduction
61 | 3) Line processing
62 | 4) Field separators
63 | 5) Record separators
64 | 6) Multiple file input
65 | 7) Processing multiple records
66 | 8) Two file processing
67 | 9) Dealing with duplicates
68 | 10) Processing structured data
69 |
70 |
71 |
72 | # Acknowledgements
73 |
74 | * [ruby-lang documentation](https://www.ruby-lang.org/en/documentation/) — manuals and tutorials
75 | * [stackoverflow](https://stackoverflow.com/) — for getting answers to pertinent questions on Ruby and related commands
76 | * [tex.stackexchange](https://tex.stackexchange.com/) — for help on [pandoc](https://github.com/jgm/pandoc/) and `tex` related questions
77 | * [/r/ruby/](https://old.reddit.com/r/ruby/) — helpful forum
78 | * [canva](https://www.canva.com/) — cover image
79 | * [oxipng](https://github.com/shssoichiro/oxipng), [pngquant](https://pngquant.org/) and [svgcleaner](https://github.com/RazrFalcon/svgcleaner) — optimizing images
80 | * [Warning](https://commons.wikimedia.org/wiki/File:Warning_icon.svg) and [Info](https://commons.wikimedia.org/wiki/File:Info_icon_002.svg) icons by [Amada44](https://commons.wikimedia.org/wiki/User:Amada44) under public domain
81 | * **KOTP** for spotting grammatical mistakes
82 | * [mdBook](https://github.com/rust-lang/mdBook) — for web version of the book
83 | * [mdBook-pagetoc](https://github.com/JorelAli/mdBook-pagetoc) — for adding table of contents for each chapter
84 | * [minify-html](https://github.com/wilsonzlin/minify-html) — for minifying html files
85 |
86 | A heartfelt thanks to all my readers. Your valuable support has significantly eased my financial concerns and allows me to continue working on programming ebooks.
87 |
88 |
89 |
90 | # License
91 |
92 | The book is licensed under a [Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License](https://creativecommons.org/licenses/by-nc-sa/4.0/).
93 |
94 | The code snippets are licensed under MIT, see [LICENSE](./LICENSE) file.
95 |
96 |
--------------------------------------------------------------------------------
/code_snippets/Line_processing.sh:
--------------------------------------------------------------------------------
1 | ## Regexp based filtering
2 |
3 | cat table.txt
4 |
5 | ruby -ne 'print if /-|ow\b/' table.txt
6 |
7 | ruby -ne 'print if !/[ksy]/' table.txt
8 |
9 | printf 'gate\napple\nwhat\n' | ruby -ne '/at$/ && print'
10 |
11 | printf 'gate\napple\nwhat\n' | ruby -ne '$_ =~ /at$/ && print'
12 |
13 | cat paths.txt
14 |
15 | ruby -ne 'print if /\/home\/ram\//' paths.txt
16 |
17 | ruby -ne 'print if %r{/home/ram/}' paths.txt
18 |
19 | ruby -ne 'print if !%r#/home/ram/#' paths.txt
20 |
21 | ## Extracting matched portions
22 |
23 | cat ip.txt
24 |
25 | ruby -ne 'puts $& if /\b[a-z]\w*[ty]\b/' ip.txt
26 |
27 | ruby -ne 'puts "#{$1}::#{$2}" if /(\b[bdp]\w+).*(\b[a-f]\w+)/i' ip.txt
28 |
29 | ## match? method
30 |
31 | ruby -ne 'print if $_.match?(/[AB]|the\b/)' ip.txt
32 |
33 | ## Transliteration
34 |
35 | echo 'Uryyb Jbeyq' | ruby -pe '$_.tr!("a-zA-Z", "n-za-mN-ZA-M")'
36 |
37 | echo 'apple:123:banana' | ruby -pe '$_.tr!("^0-9\n", "-")'
38 |
39 | echo 'apple:123:banana' | ruby -pe '$_.tr!("^0-9\n", "")'
40 |
41 | s='orange apple appleseed cab'
42 |
43 | echo "$s" | ruby -pe 'gsub(/\b(?!apple\b)\w++/) {$&.tr("a-z", "1-9")}'
44 |
45 | echo 'APPLESEED gobbledygook' | ruby -pe '$_.tr_s!("a-zA-Z", "a-zA-Z")'
46 |
47 | echo 'APPLESEED gobbledygook' | ruby -pe '$_.tr_s!("A-Z", "a-z")'
48 |
49 | ## Conditional substitution
50 |
51 | printf '1,2,3,4\na,b,c,d\n' | ruby -pe 'gsub(/,/, "-") if !/2/'
52 |
53 | ruby -ne 'print gsub(/ark/, "[\\0]") if /the/' ip.txt
54 |
55 | ruby -ne 'print if $_.gsub!(/\bw\w*t\b/, "{\\0}")' ip.txt
56 |
57 | ## Multiple conditions
58 |
59 | ruby -ne 'print if /ark/ && !/sky/' ip.txt
60 |
61 | ruby -ane 'print if /\bthe\b/ || $F.size == 5' ip.txt
62 |
63 | ## next
64 |
65 | ruby -ne '(puts "%% #{$_}"; next) if /\bpar/;
66 | puts /s/ ? "X" : "Y"' word_anchors.txt
67 |
68 | ## exit
69 |
70 | ruby -ne 'print; exit if /say/' ip.txt
71 |
72 | ruby -pe 'exit if /say/' ip.txt
73 |
74 | tac ip.txt | ruby -ne 'print; exit if /an/' | tac
75 |
76 | printf 'sea\neat\ndrop\n' | ruby -ne 'print; exit(2) if /at/'
77 |
78 | echo $?
79 |
80 | ruby -pe 'exit if /cake/' table.txt
81 |
82 | ruby -pe 'exit if /cake/; END{puts "bye"}' table.txt
83 |
84 | ruby -pe 'BEGIN{puts "hi"; exit; puts "hello"}; END{puts "bye"}' table.txt
85 |
86 | ## Line number based processing
87 |
88 | ruby -ne 'print if $. == 3' ip.txt
89 |
90 | ruby -ne 'print if $. == 2 || $. == 6' ip.txt
91 |
92 | printf 'gates\nnot\nused\n' | ruby -pe '$_.tr!("a-z", "*") if $. == 2'
93 |
94 | seq 14 25 | ruby -ne 'print if $. >= 10'
95 |
96 | ruby -ne 'print if $<.eof' ip.txt
97 |
98 | ruby -ne 'puts "#{$.}:#{$_}" if $<.eof' ip.txt
99 |
100 | ruby -ne 'print if $<.eof' ip.txt table.txt
101 |
102 | seq 3542 4623452 | ruby -ne '(print; exit) if $. == 2452'
103 |
104 | seq 3542 4623452 | ruby -ne 'print if $. == 250; (print; exit) if $. == 2452'
105 |
106 | time seq 3542 4623452 | ruby -ne '(print; exit) if $. == 2452' > f1
107 |
108 | time seq 3542 4623452 | ruby -ne 'print if $. == 2452' > f2
109 |
110 | rm f1 f2
111 |
112 | ## Flip-Flop operator
113 |
114 | seq 14 25 | ruby -ne 'print if 3..5'
115 |
116 | seq 14 25 | ruby -ne 'print if (3...5).include?($.)'
117 |
118 | ruby -ne 'print if /to/../pl/' ip.txt
119 |
120 | ruby -ne 'print if 6../utter/' ip.txt
121 |
122 | ruby -ne 'print if !(/\bba/..$<.eof)' ip.txt table.txt
123 |
124 | ruby -ne 'print if 7../and/' ip.txt
125 |
126 | ruby -ne 'print if 7.../and/' ip.txt
127 |
128 | ruby -ne 'print if /Banana/../XYZ/' ip.txt
129 |
130 | ## Working with fixed strings
131 |
132 | printf 'int a[5]\nfig\n1+4=5\n' | ruby -ne 'print if /a[5]/'
133 |
134 | printf 'int a[5]\nfig\n1+4=5\n' | ruby -ne 'print if $_.include?("a[5]")'
135 |
136 | printf 'int a[5]\nfig\n1+4=5\n' | ruby -pe 'sub(/a[5]/, "b")'
137 |
138 | printf 'int a[5]\nfig\n1+4=5\n' | ruby -pe 'sub("a[5]", "b")'
139 |
140 | ruby -e 'a=5; puts "value of a:\t#{a}"'
141 |
142 | echo 'int #{a}' | ruby -ne 'print if $_.include?(%q/#{a}/)'
143 |
144 | echo 'int #{a}' | ruby -pe 'sub(%q/#{a}/, "b")'
145 |
146 | echo 'int #{a}' | s='#{a}' ruby -ne 'print if $_.include?(ENV["s"])'
147 |
148 | echo 'int #{a\\}' | s='#{a\\}' ruby -pe 'sub(ENV["s"], "b")'
149 |
150 | echo 'int a' | s='x\\y\0z' ruby -pe 'sub(/a/, ENV["s"])'
151 |
152 | echo 'int a' | s='x\\y\0z' ruby -pe 'sub(/a/) {ENV["s"]}'
153 |
154 | cat eqns.txt
155 |
156 | s='a+b' ruby -ne 'print if $_.start_with?(ENV["s"])' eqns.txt
157 |
158 | s='a+b' ruby -lne 'print if $_.end_with?(ENV["s"])' eqns.txt
159 |
160 | ruby -ne 'print if $_.index("a+b")' eqns.txt
161 |
162 | ruby -ne 'print if $_.index("a+b")==0' eqns.txt
163 |
164 | ruby -ne '$i = $_.index("="); print if $i && $i < 6' eqns.txt
165 |
166 | s='a+b' ruby -ne 'print if $_.index(ENV["s"], 1)' eqns.txt
167 |
168 | printf 'a.b\na+b\n' | ruby -lne 'print if /^a.b$/'
169 |
170 | printf 'a.b\na+b\n' | ruby -lne 'print if $_ == %q/a.b/'
171 |
172 | printf '1 a.b\n2 a+b\n' | ruby -lane 'print if $F[1] != %q/a.b/'
173 |
174 | ## In-place file editing
175 |
176 | cat colors.txt
177 |
178 | ruby -i.bkp -pe 'sub(/blue/, "-green-")' colors.txt
179 |
180 | cat colors.txt
181 |
182 | cat colors.txt.bkp
183 |
184 | cat t1.txt
185 |
186 | cat t2.txt
187 |
188 | ruby -i.bkp -pe 'sub(/bad/, "good")' t1.txt t2.txt
189 |
190 | ls t?.*
191 |
192 | cat t1.txt
193 |
194 | cat t2.txt
195 |
196 | cat fruits.txt
197 |
198 | ruby -i -pe 'gsub(/(..)\1/) {$&.upcase}' fruits.txt
199 |
200 | cat fruits.txt
201 |
202 |
--------------------------------------------------------------------------------
/code_snippets/Field_separators.sh:
--------------------------------------------------------------------------------
1 | ## Default field separation
2 |
3 | echo ' a b c ' | ruby -ane 'puts $F.size'
4 |
5 | echo ' a b c ' | ruby -ane 'puts "(#{$F[0]})"'
6 |
7 | echo ' a b c ' | ruby -ane 'puts "(#{$F[-1]})"'
8 |
9 | printf ' one \t\f\v two\t\r\tthree \t\r ' | ruby -ane 'puts $F.size'
10 |
11 | printf ' one \t\f\v two\t\r\tthree \t\r ' | ruby -ane 'puts $F[1] + "."'
12 |
13 | ## Input field separator
14 |
15 | echo 'goal:amazing:whistle:kwality' | ruby -F: -ane 'puts $F[0], $F[-1], $F[1]'
16 |
17 | echo 'one;two;three;four' | ruby -F';' -ane 'puts $F[2]'
18 |
19 | echo 'load;err_msg--\ant,r2..not' | ruby -F'\W+' -ane 'puts $F[2]'
20 |
21 | echo 'hi.bye.hello' | ruby -F'\.' -ane 'puts $F[1]'
22 |
23 | printf 'COOL\nnice car\n' | ruby -F'(?i)[aeiou]' -ane 'puts $F.size - 1'
24 |
25 | ## Character-wise separation
26 |
27 | echo 'apple' | ruby -ne 'puts $_[0]'
28 |
29 | ruby -e 'puts Encoding.default_external'
30 |
31 | LC_ALL=C ruby -e 'puts Encoding.default_external'
32 |
33 | echo 'fox:αλεπού' | ruby -ne 'puts $_[4..5]'
34 |
35 | echo 'fox:αλεπού' | ruby -E UTF-8:UTF-8 -ne 'puts $_[4..5]'
36 |
37 | ## Newline character in the last field
38 |
39 | echo 'cat dog' | ruby -ane 'puts "[#{$F[-1]}]"'
40 |
41 | echo 'cat:dog' | ruby -F: -ane 'puts "[#{$F[-1]}]"'
42 |
43 | printf 'cat:dog' | ruby -F: -ane 'puts "[#{$F[-1]}]"'
44 |
45 | echo ' a b c ' | ruby -ane 'puts $F.size'
46 |
47 | echo ':a:b:c:' | ruby -F: -ane 'puts $F.size; puts "[#{$F[-1]}]"'
48 |
49 | ## Using the -l option for field splitting
50 |
51 | echo 'cat:dog' | ruby -F: -lane 'puts "[#{$F[-1]}]"'
52 |
53 | echo 'cat:dog' | ruby -F: -lane 'print "[#{$F[-1]}]"'
54 |
55 | echo ':a:b:c:' | ruby -F: -lane 'puts $F.size'
56 |
57 | echo ':a:b:c:' | ruby -lane 'puts $_.split(/:/, -1).size'
58 |
59 | ## Output field separator
60 |
61 | ruby -lane 'BEGIN{$, = " "}; print $F[0], $F[2]' table.txt
62 |
63 | ruby -lane 'puts "#{$F[0]} #{$F[2]}"' table.txt
64 |
65 | echo 'Sample123string42with777numbers' | ruby -F'\d+' -lane 'puts $F.join(",")'
66 |
67 | s='goal:amazing:whistle:kwality'
68 |
69 | echo "$s" | ruby -F: -lane 'puts $F.values_at(-1, 1, 0).join("-")'
70 |
71 | echo "$s" | ruby -F: -lane '$F.append(42); puts $F * "::"'
72 |
73 | ## scan method
74 |
75 | s='Sample123string42with777numbers'
76 |
77 | echo "$s" | ruby -ne 'puts $_.scan(/\d+/)[1]'
78 |
79 | s='coat Bin food tar12 best Apple fig_42'
80 |
81 | echo "$s" | ruby -ne 'puts $_.scan(/\b[a-z0-9]+\b/) * ","'
82 |
83 | s='items: "apple" and "mango"'
84 |
85 | echo "$s" | ruby -ne 'puts $_.scan(/"[^"]+"/)[1]'
86 |
87 | echo "$s" | ruby -ne 'puts $_[/"[^"]+"/]'
88 |
89 | s='eagle,"fox,42",bee,frog'
90 |
91 | echo "$s" | ruby -F, -lane 'puts $F[1]'
92 |
93 | echo "$s" | ruby -lne 'puts $_.scan(/"[^"]*"|[^,]+/)[1]'
94 |
95 | ## Fixed width processing
96 |
97 | cat items.txt
98 |
99 | ruby -ne 'puts $_.unpack("a8a4a6") * ","' items.txt
100 |
101 | ruby -ne 'puts $_.unpack("a8a4a6")[1]' items.txt
102 |
103 | ruby -ne 'puts $_.unpack("a5x3a3xa6") * ","' items.txt
104 |
105 | printf 'banana\x0050\x00' | ruby -ne 'puts $_.unpack("Z*Z*") * ":"'
106 |
107 | ruby -ne 'puts $_.unpack("a5x3a*") * ","' items.txt
108 |
109 | echo 'b 123 good' | ruby -ne 'puts $_[2,3]'
110 |
111 | echo 'b 123 good' | ruby -ne 'puts $_[6,4]'
112 |
113 | echo 'b 123 good' | ruby -lpe '$_[2,3] = "gleam"'
114 |
115 | ## Assorted field processing methods
116 |
117 | s='goal:amazing:42:whistle:kwality:3.14'
118 |
119 | echo "$s" | ruby -F: -lane 'puts $F.grep(/i[nts]/) * ":"'
120 |
121 | echo "$s" | ruby -F: -lane 'puts $F.grep_v(/\d/) * ":"'
122 |
123 | ruby -lane 'print if $F.grep(/r/).size <= 1' table.txt
124 |
125 | s='goal:amazing:42:whistle:kwality:3.14'
126 |
127 | echo "$s" | ruby -F: -lane 'puts $F.map(&:upcase) * ":"'
128 |
129 | echo '23 756 -983 5' | ruby -ane 'puts $F.map {_1.to_i ** 2} * " "'
130 |
131 | echo 'AaBbCc' | ruby -lne 'puts $_.chars.map(&:ord) * " "'
132 |
133 | echo '3.14,17,6' | ruby -F, -ane 'puts $F.map(&:to_f).sum'
134 |
135 | s='hour hand band mat heated pineapple'
136 |
137 | echo "$s" | ruby -ane 'puts $F.filter {_1[0]!="h" && _1.size<6}'
138 |
139 | echo "$s" | ruby -ane 'puts $F.filter_map {|w|
140 | w.gsub(/[ae]/, "X") if w[0]=="h"}'
141 |
142 | echo '3.14,17,6' | ruby -F, -lane 'puts $F.map(&:to_f).reduce(100, :+)'
143 |
144 | echo '3.14,17,6' | ruby -F, -lane 'puts $F.map(&:to_f).reduce(:*)'
145 |
146 | echo '3.14,17,6' | ruby -F, -lane 'puts $F.reduce(2) {|op,n| op*n.to_f}'
147 |
148 | s='floor bat to dubious four'
149 |
150 | echo "$s" | ruby -ane 'puts $F.sort * ":"'
151 |
152 | echo "$s" | ruby -ane 'puts $F.sort_by(&:size) * ":"'
153 |
154 | echo '23 756 -983 5' | ruby -lane 'puts $F.sort_by(&:to_i) * ":"'
155 |
156 | echo 'dragon' | ruby -lne 'puts $_.chars.sort.reverse * ""'
157 |
158 | s='try a bad to good i teal by nice how'
159 |
160 | echo "$s" | ruby -ane 'puts $F.sort_by {|w| [-w.size, w]} * ":"'
161 |
162 | s='3,b,a,3,c,d,1,d,c,2,2,2,3,1,b'
163 |
164 | echo "$s" | ruby -F, -lane 'puts $F.uniq * ","'
165 |
166 | cat marks.txt
167 |
168 | ruby -ane 'idx = $F.each_index.sort {$F[_2] <=> $F[_1]} if $.==1;
169 | puts $F.values_at(*idx) * "\t"' marks.txt
170 |
171 | s='floor bat to dubious four'
172 |
173 | echo "$s" | ruby -ane 'puts $F.shuffle * ":"'
174 |
175 | echo 'foobar' | ruby -lne 'print $_.chars.shuffle * ""'
176 |
177 | s='hour hand band mat heated pineapple'
178 |
179 | echo "$s" | ruby -ane 'puts $F.sample'
180 |
181 | echo "$s" | ruby -ane 'puts $F.sample(2)'
182 |
183 |
--------------------------------------------------------------------------------
/exercises/Exercises.md:
--------------------------------------------------------------------------------
1 | # Exercises
2 |
3 | > For solutions, see [Exercise_solutions.md](https://github.com/learnbyexample/learn_ruby_oneliners/blob/master/exercises/Exercise_solutions.md).
4 |
5 |
6 |
7 | # One-liner introduction
8 |
9 | **1)** For the input file `ip.txt`, display all lines containing `is`.
10 |
11 | ```bash
12 | $ cat ip.txt
13 | Hello World
14 | How are you
15 | This game is good
16 | Today is sunny
17 | 12345
18 | You are funny
19 |
20 | ##### add your solution here
21 | This game is good
22 | Today is sunny
23 | ```
24 |
25 | **2)** For the input file `ip.txt`, display the first field of lines *not* containing `y`. Consider space as the field separator for this file.
26 |
27 | ```bash
28 | ##### add your solution here
29 | Hello
30 | This
31 | 12345
32 | ```
33 |
34 | **3)** For the input file `ip.txt`, display all lines containing no more than 2 fields.
35 |
36 | ```bash
37 | ##### add your solution here
38 | Hello World
39 | 12345
40 | ```
41 |
42 | **4)** For the input file `ip.txt`, display all lines containing `is` in the second field.
43 |
44 | ```bash
45 | ##### add your solution here
46 | Today is sunny
47 | ```
48 |
49 | **5)** For each line of the input file `ip.txt`, replace the first occurrence of `o` with `0`.
50 |
51 | ```bash
52 | ##### add your solution here
53 | Hell0 World
54 | H0w are you
55 | This game is g0od
56 | T0day is sunny
57 | 12345
58 | Y0u are funny
59 | ```
60 |
61 | **6)** For the input file `table.txt`, calculate and display the product of numbers in the last field of each line. Consider space as the field separator for this file.
62 |
63 | ```bash
64 | $ cat table.txt
65 | brown bread mat hair 42
66 | blue cake mug shirt -7
67 | yellow banana window shoes 3.14
68 |
69 | ##### add your solution here
70 | -923.1600000000001
71 | ```
72 |
73 | **7)** Append `.` to all the input lines for the given stdin data.
74 |
75 | ```bash
76 | $ printf 'last\nappend\nstop\ntail\n' | ##### add your solution here
77 | last.
78 | append.
79 | stop.
80 | tail.
81 | ```
82 |
83 | **8)** Use contents of the `s` variable to display matching lines from the input file `ip.txt`. Assume that `s` doesn't have any regexp metacharacters. Construct the solution such that there's at least one word character immediately preceding the contents of the `s` variable.
84 |
85 | ```bash
86 | $ s='is'
87 |
88 | ##### add your solution here
89 | This game is good
90 | ```
91 |
92 | **9)** Use `system` to display the contents of the filename present in the second field of the given input line. Consider space as the field separator.
93 |
94 | ```bash
95 | $ s='report.log ip.txt sorted.txt'
96 | $ echo "$s" | ##### add your solution here
97 | Hello World
98 | How are you
99 | This game is good
100 | Today is sunny
101 | 12345
102 | You are funny
103 |
104 | $ s='power.txt table.txt'
105 | $ echo "$s" | ##### add your solution here
106 | brown bread mat hair 42
107 | blue cake mug shirt -7
108 | yellow banana window shoes 3.14
109 | ```
110 |
111 |
112 |
113 | # Line processing
114 |
115 | **1)** For the given input, display except the third line.
116 |
117 | ```bash
118 | $ seq 34 37 | ##### add your solution here
119 | 34
120 | 35
121 | 37
122 | ```
123 |
124 | **2)** Display only the fourth, fifth, sixth and seventh lines for the given input.
125 |
126 | ```bash
127 | $ seq 65 78 | ##### add your solution here
128 | 68
129 | 69
130 | 70
131 | 71
132 | ```
133 |
134 | **3)** For the input file `ip.txt`, replace all occurrences of `are` with `are not` and `is` with `is not` only from line number **4** till the end of file. Also, only the lines that were changed should be displayed in the output.
135 |
136 | ```bash
137 | $ cat ip.txt
138 | Hello World
139 | How are you
140 | This game is good
141 | Today is sunny
142 | 12345
143 | You are funny
144 |
145 | ##### add your solution here
146 | Today is not sunny
147 | You are not funny
148 | ```
149 |
150 | **4)** For the given stdin, display only the first three lines. Avoid processing lines that are not relevant.
151 |
152 | ```bash
153 | $ seq 14 25 | ##### add your solution here
154 | 14
155 | 15
156 | 16
157 | ```
158 |
159 | **5)** For the input file `ip.txt`, display all lines from the start of the file till the first occurrence of `game`.
160 |
161 | ```bash
162 | ##### add your solution here
163 | Hello World
164 | How are you
165 | This game is good
166 | ```
167 |
168 | **6)** For the input file `ip.txt`, display all lines that contain `is` but not `good`.
169 |
170 | ```bash
171 | ##### add your solution here
172 | Today is sunny
173 | ```
174 |
175 | **7)** For the input file `ip.txt`, extract the word before the whole word `is` as well as the word after it. If such a match is found, display the two words around `is` in reversed order. For example, `hi;1 is--234 bye` should be converted to `234:1`. Assume that the whole word `is` will not be present more than once in a single line.
176 |
177 | ```bash
178 | ##### add your solution here
179 | good:game
180 | sunny:Today
181 | ```
182 |
183 | **8)** For the input file `hex.txt`, replace all occurrences of `0xA0` with `0x50` and `0xFF` with `0x7F`.
184 |
185 | ```bash
186 | $ cat hex.txt
187 | start: 0xA0, func1: 0xA0
188 | end: 0xFF, func2: 0xB0
189 | restart: 0xA010, func3: 0x7F
190 |
191 | ##### add your solution here
192 | start: 0x50, func1: 0x50
193 | end: 0x7F, func2: 0xB0
194 | restart: 0x5010, func3: 0x7F
195 | ```
196 |
197 | **9)** For the input file `text.txt`, replace all occurrences of `in` with `an` and write back the changes to `text.txt` itself. The original contents should get saved to `text.txt.orig`.
198 |
199 | ```bash
200 | $ cat text.txt
201 | can ran want plant
202 | tin fin fit mine line
203 |
204 | ##### add your solution here
205 |
206 | $ cat text.txt
207 | can ran want plant
208 | tan fan fit mane lane
209 | $ cat text.txt.orig
210 | can ran want plant
211 | tin fin fit mine line
212 | ```
213 |
214 | **10)** For the input file `text.txt`, replace all occurrences of `an` with `in` and write back the changes to `text.txt` itself. Do not create backups for this exercise. Note that you should have solved the previous exercise before starting this one.
215 |
216 | ```bash
217 | $ cat text.txt
218 | can ran want plant
219 | tan fan fit mane lane
220 |
221 | ##### add your solution here
222 |
223 | $ cat text.txt
224 | cin rin wint plint
225 | tin fin fit mine line
226 | $ diff text.txt text.txt.orig
227 | 1c1
228 | < cin rin wint plint
229 | ---
230 | > can ran want plant
231 | ```
232 |
233 | **11)** Find the starting index of first occurrence of `is` or `the` or `was` or `to` for each input line of the file `idx.txt`. Assume that every input line will match at least one of these terms.
234 |
235 | ```bash
236 | $ cat idx.txt
237 | match after the last newline character
238 | and then you want to test
239 | this is good bye then
240 | you were there to see?
241 |
242 | ##### add your solution here
243 | 12
244 | 4
245 | 2
246 | 9
247 | ```
248 |
249 | **12)** Display all lines containing `[4]*` for the given stdin data.
250 |
251 | ```bash
252 | $ printf '2.3/[4]*6\n2[4]5\n5.3-[4]*9\n' | ##### add your solution here
253 | 2.3/[4]*6
254 | 5.3-[4]*9
255 | ```
256 |
257 | **13)** For the given input string, change all lowercase alphabets to `x` only for words starting with `m`.
258 |
259 | ```bash
260 | $ s='ma2T3a a2p kite e2e3m meet'
261 |
262 | $ echo "$s" | ##### add your solution here
263 | xx2T3x a2p kite e2e3m xxxx
264 | ```
265 |
266 | **14)** For the input file `ip.txt`, delete all characters other than lowercase vowels and the newline character. Perform this transformation only between a line containing `you` up to line number `4` (inclusive).
267 |
268 | ```bash
269 | ##### add your solution here
270 | Hello World
271 | oaeou
272 | iaeioo
273 | oaiu
274 | 12345
275 | You are funny
276 | ```
277 |
278 | **15)** For the input file `sample.txt`, display from the start of the file till the first occurrence of `are`, excluding the matching line.
279 |
280 | ```bash
281 | $ cat sample.txt
282 | Hello World
283 |
284 | Good day
285 | How are you
286 |
287 | Just do-it
288 | Believe it
289 |
290 | Today is sunny
291 | Not a bit funny
292 | No doubt you like it too
293 |
294 | Much ado about nothing
295 | He he he
296 |
297 | ##### add your solution here
298 | Hello World
299 |
300 | Good day
301 | ```
302 |
303 | **16)** For the input file `sample.txt`, display from the last occurrence of `do` till the end of the file.
304 |
305 | ```bash
306 | ##### add your solution here
307 | Much ado about nothing
308 | He he he
309 | ```
310 |
311 | **17)** For the input file `sample.txt`, display from the 9th line till a line containing `you`.
312 |
313 | ```bash
314 | ##### add your solution here
315 | Today is sunny
316 | Not a bit funny
317 | No doubt you like it too
318 | ```
319 |
320 | **18)** Display only the odd numbered lines from `ip.txt`.
321 |
322 | ```bash
323 | ##### add your solution here
324 | Hello World
325 | This game is good
326 | 12345
327 | ```
328 |
329 | **19)** For the `table.txt` file, print only the line number for lines containing `air` or `win`.
330 |
331 | ```bash
332 | $ cat table.txt
333 | brown bread mat hair 42
334 | blue cake mug shirt -7
335 | yellow banana window shoes 3.14
336 |
337 | ##### add your solution here
338 | 1
339 | 3
340 | ```
341 |
342 | **20)** For the input file `table.txt`, calculate the sum of numbers in the last column, excluding the second line.
343 |
344 | ```bash
345 | ##### add your solution here
346 | 45.14
347 | ```
348 |
349 | **21)** Print the second and fourth line for every block of five lines.
350 |
351 | ```bash
352 | $ seq 15 | ##### add your solution here
353 | 2
354 | 4
355 | 7
356 | 9
357 | 12
358 | 14
359 | ```
360 |
361 | **22)** For the input file `ip.txt`, display all lines containing `e` or `u` but not both.
362 |
363 | ```bash
364 | ##### add your solution here
365 | Hello World
366 | This game is good
367 | Today is sunny
368 | ```
369 |
370 |
371 |
372 | # Field separators
373 |
374 | **1)** For the input file `brackets.txt`, extract only the contents between `()` or `)(` from each input line. Assume that `()` characters will be present only once every line.
375 |
376 | ```bash
377 | $ cat brackets.txt
378 | foo blah blah(ice) 123 xyz$
379 | (almond-pista) choco
380 | yo )yoyo( yo
381 |
382 | ##### add your solution here
383 | ice
384 | almond-pista
385 | yoyo
386 | ```
387 |
388 | **2)** For the input file `scores.csv`, extract `Name` and `Physics` fields in the format shown below.
389 |
390 | ```bash
391 | $ cat scores.csv
392 | Name,Maths,Physics,Chemistry
393 | Blue,67,46,99
394 | Lin,78,83,80
395 | Er,56,79,92
396 | Cy,97,98,95
397 | Ort,68,72,66
398 | Ith,100,100,100
399 |
400 | ##### add your solution here
401 | Name:Physics
402 | Blue:46
403 | Lin:83
404 | Er:79
405 | Cy:98
406 | Ort:72
407 | Ith:100
408 | ```
409 |
410 | **3)** For the input file `scores.csv`, display names of those who've scored above `70` in Maths.
411 |
412 | ```bash
413 | ##### add your solution here
414 | Lin
415 | Cy
416 | Ith
417 | ```
418 |
419 | **4)** Display the number of word characters for the given inputs. Word definition here is same as used in regular expressions. Can you construct a solution with `gsub` and one without the substitution functions?
420 |
421 | ```bash
422 | # solve using gsub
423 | $ echo 'hi there' | ##### add your solution here
424 | 7
425 |
426 | # solve without using the substitution functions
427 | $ echo 'u-no;co%."(do_12:as' | ##### add your solution here
428 | 12
429 | ```
430 |
431 | **5)** For the input file `quoted.txt`, extract the sequence of characters surrounded by double quotes and display them in the format shown below.
432 |
433 | ```bash
434 | $ cat quoted.txt
435 | 1 "grape" and "mango" and "guava"
436 | ("c 1""d""a-2""b")
437 |
438 | ##### add your solution here
439 | "grape","guava","mango"
440 | "a-2","b","c 1","d"
441 | ```
442 |
443 | **6)** Display only the third and fifth characters from each input line.
444 |
445 | ```bash
446 | $ printf 'restore\ncat one\ncricket' | ##### add your solution here
447 | so
448 | to
449 | ik
450 | ```
451 |
452 | **7)** Transform the given input file `fw.txt` to get the output as shown below. If the second field is empty (i.e. contains only space characters), replace it with `NA`.
453 |
454 | ```bash
455 | $ cat fw.txt
456 | 1.3 rs 90 0.134563
457 | 3.8 6
458 | 5.2 ye 8.2387
459 | 4.2 kt 32 45.1
460 |
461 | ##### add your solution here
462 | 1.3,rs,0.134563
463 | 3.8,NA,6
464 | 5.2,ye,8.2387
465 | 4.2,kt,45.1
466 | ```
467 |
468 | **8)** For the input file `scores.csv`, display the header as well as any row which contains `b` or `t` (irrespective of case) in the first field.
469 |
470 | ```bash
471 | ##### add your solution here
472 | Name,Maths,Physics,Chemistry
473 | Blue,67,46,99
474 | Ort,68,72,66
475 | Ith,100,100,100
476 | ```
477 |
478 | **9)** Extract all whole words containing `42` but not at the edge of a word. Assume a word cannot contain `42` more than once.
479 |
480 | ```bash
481 | $ s='hi42bye nice1423 bad42 cool_42a 42fake'
482 | $ echo "$s" | ##### add your solution here
483 | hi42bye
484 | nice1423
485 | cool_42a
486 | ```
487 |
488 | **10)** For the input file `scores.csv`, add another column named **GP** which is calculated out of 100 by giving 50% weightage to Maths and 25% each for Physics and Chemistry.
489 |
490 | ```bash
491 | ##### add your solution here
492 | Name,Maths,Physics,Chemistry,GP
493 | Blue,67,46,99,69.75
494 | Lin,78,83,80,79.75
495 | Er,56,79,92,70.75
496 | Cy,97,98,95,96.75
497 | Ort,68,72,66,68.5
498 | Ith,100,100,100,100.0
499 | ```
500 |
501 | **11)** For the input file `mixed_fs.txt`, retain only the first two fields from each input line. The input and output field separators should be space for first two lines and `,` for the rest of the lines.
502 |
503 | ```bash
504 | $ cat mixed_fs.txt
505 | rose lily jasmine tulip
506 | pink blue white yellow
507 | car,mat,ball,basket
508 | light green,brown,black,purple
509 | apple,banana,cherry
510 |
511 | ##### add your solution here
512 | rose lily
513 | pink blue
514 | car,mat
515 | light green,brown
516 | apple,banana
517 | ```
518 |
519 | **12)** For the given space separated numbers, filter only numbers in the range `20` to `1000` (inclusive).
520 |
521 | ```bash
522 | $ s='20 -983 5 756 634223 1000'
523 |
524 | $ echo "$s" | ##### add your solution here
525 | 20 756 1000
526 | ```
527 |
528 | **13)** For the given space separated words, randomize the order of characters for each word.
529 |
530 | ```bash
531 | $ s='this is a sample sentence'
532 |
533 | # sample randomized output shown here, could be different for you
534 | $ echo "$s" | ##### add your solution here
535 | shti si a salemp sneentce
536 | ```
537 |
538 | **14)** For the given input file `words.txt`, filter all lines containing characters in ascending and descending order.
539 |
540 | ```bash
541 | $ cat words.txt
542 | bot
543 | art
544 | are
545 | boat
546 | toe
547 | flee
548 | reed
549 |
550 | # ascending order
551 | ##### add your solution here
552 | bot
553 | art
554 |
555 | # descending order
556 | ##### add your solution here
557 | toe
558 | reed
559 | ```
560 |
561 | **15)** For the given space separated words, extract the three longest words.
562 |
563 | ```bash
564 | $ s='I bought two bananas and three mangoes'
565 |
566 | $ echo "$s" | ##### add your solution here
567 | mangoes
568 | bananas
569 | bought
570 | ```
571 |
572 | **16)** Convert the contents of `split.txt` as shown below.
573 |
574 | ```bash
575 | $ cat split.txt
576 | apple,1:2:5,mango
577 | wry,4,look
578 | pencil,3:8,paper
579 |
580 | ##### add your solution here
581 | apple,1,mango
582 | apple,2,mango
583 | apple,5,mango
584 | wry,4,look
585 | pencil,3,paper
586 | pencil,8,paper
587 | ```
588 |
589 | **17)** For the input file `varying_fields.txt`, construct a solution to get the output shown below.
590 |
591 | ```bash
592 | $ cat varying_fields.txt
593 | hi,bye,there,was,here,to
594 | 1,2,3,4,5
595 |
596 | ##### add your solution here
597 | hi:bye:to
598 | 1:2:5
599 | ```
600 |
601 | **18)** The `fields.txt` file has fields separated by the `:` character. Delete `:` and the last field if there is a digit character anywhere before the last field. Solution shouldn't use the substitution functions.
602 |
603 | ```bash
604 | $ cat fields.txt
605 | 42:cat
606 | twelve:a2b
607 | we:be:he:0:a:b:bother
608 | apple:banana-42:cherry:
609 | dragon:unicorn:centaur
610 |
611 | ##### add your solution here
612 | 42
613 | twelve:a2b
614 | we:be:he:0:a:b
615 | apple:banana-42:cherry
616 | dragon:unicorn:centaur
617 | ```
618 |
619 | **19)** The sample string shown below uses `cat` as the field separator (irrespective of case). Use space as the output field separator and add `42` as the last field.
620 |
621 | ```bash
622 | $ s='applecatfigCaT12345cAtbanana'
623 |
624 | $ echo "$s" | ##### add your solution here
625 | apple fig 12345 banana 42
626 | ```
627 |
628 | **20)** For the input file `sample.txt`, filter lines containing 5 or more lowercase vowels.
629 |
630 | ```bash
631 | ##### add your solution here
632 | How are you
633 | Believe it
634 | No doubt you like it too
635 | Much ado about nothing
636 | ```
637 |
638 |
639 |
640 | # Record separators
641 |
642 | **1)** The input file `jumbled.txt` consists of words separated by various delimiters. Display the last four words that contain `an` or `at` or `in` or `it`, one per line.
643 |
644 | ```bash
645 | $ cat jumbled.txt
646 | overcoats;furrowing-typeface%pewter##hobby
647 | wavering:concession/woof\retailer
648 | joint[]seer{intuition}titanic
649 |
650 | ##### add your solution here
651 | wavering
652 | joint
653 | intuition
654 | titanic
655 | ```
656 |
657 | **2)** Emulate `paste -sd,` with Ruby.
658 |
659 | ```bash
660 | # this command joins all input lines with the ',' character
661 | $ paste -sd, ip.txt
662 | Hello World,How are you,This game is good,Today is sunny,12345,You are funny
663 |
664 | # make sure there's no ',' at the end of the line
665 | # and that there's a newline character at the end of the line
666 | ##### add your solution here
667 | Hello World,How are you,This game is good,Today is sunny,12345,You are funny
668 |
669 | # if there's only one line in input, again make sure there's no trailing ','
670 | # and that there's a newline character at the end of the line
671 | $ printf 'fig' | paste -sd,
672 | fig
673 | $ printf 'fig' | ##### add your solution here
674 | fig
675 | ```
676 |
677 | **3)** For the input file `sample.txt`, extract all paragraphs having words starting with `do`.
678 |
679 | ```bash
680 | $ cat sample.txt
681 | Hello World
682 |
683 | Good day
684 | How are you
685 |
686 | Just do-it
687 | Believe it
688 |
689 | Today is sunny
690 | Not a bit funny
691 | No doubt you like it too
692 |
693 | Much ado about nothing
694 | He he he
695 |
696 | # note that there's no extra empty line at the end of the output
697 | ##### add your solution here
698 | Just do-it
699 | Believe it
700 |
701 | Today is sunny
702 | Not a bit funny
703 | No doubt you like it too
704 | ```
705 |
706 | **4)** For the input file `sample.txt`, change each paragraph to a single line by joining lines using `.` and a space character as the separator. Also, add a final `.` to each paragraph.
707 |
708 | ```bash
709 | # note that there's no extra empty line at the end of the output
710 | ##### add your solution here
711 | Hello World.
712 |
713 | Good day. How are you.
714 |
715 | Just do-it. Believe it.
716 |
717 | Today is sunny. Not a bit funny. No doubt you like it too.
718 |
719 | Much ado about nothing. He he he.
720 | ```
721 |
722 | **5)** For the given input, use `;;` as the record separators and `:` as the field separators. Filter records whose second field is greater than `50`.
723 |
724 | ```bash
725 | $ s='mango:100;;apple:25;;grapes:75'
726 |
727 | # note that the output has ;; at the end, not a newline character
728 | $ printf "$s" | ##### add your solution here
729 | mango:100;;grapes:75;;
730 | ```
731 |
732 | **6)** The input file `f1.txt` has varying amount of empty lines between the records. Change them to be always two empty lines. Also, remove empty lines at the start and end of the file.
733 |
734 | ```bash
735 | ##### add your solution here
736 | hello
737 |
738 |
739 | world
740 |
741 |
742 | apple
743 | banana
744 | cherry
745 |
746 |
747 | tea coffee
748 | chocolate
749 | ```
750 |
751 | **7)** The sample string shown below uses `cat` as the record separator. Display only the even numbered records separated by a single empty line.
752 |
753 | ```bash
754 | $ s='applecatfigcat12345catbananacatguava:cat:mangocat3'
755 | $ echo "$s" | ##### add your solution here
756 | fig
757 |
758 | banana
759 |
760 | :mango
761 | ```
762 |
763 |
764 |
765 | # Multiple file input
766 |
767 | **1)** Print the last field of first two lines for the input files `table.txt` and `ip.txt`. Assume space as the field separators for these two files. To make the output more informative, print filenames and a separator as shown in the output below. Assume that the input files will have at least two lines.
768 |
769 | ```bash
770 | # table.txt ip.txt are passed as file inputs
771 | ##### add your solution here
772 | >table.txt<
773 | 42
774 | -7
775 | ----------
776 | >ip.txt<
777 | World
778 | you
779 | ----------
780 | ```
781 |
782 | **2)** For the input files `sample.txt`, `secrets.txt`, `ip.txt` and `table.txt`, display only the names of files that contain `at` or `fun` in the third field. Assume space as the field separator.
783 |
784 | ```bash
785 | ##### add your solution here
786 | secrets.txt
787 | ip.txt
788 | table.txt
789 | ```
790 |
791 | **3)** Print the first two lines from the input files `ip.txt`, `sample.txt` and `table.txt`. Also, add a separator between the results as shown below (note that the separator isn't present at the end of the output). Assume that the input files will have at least two lines.
792 |
793 | ```bash
794 | ##### add your solution here
795 | Hello World
796 | How are you
797 | ---
798 | Hello World
799 |
800 | ---
801 | brown bread mat hair 42
802 | blue cake mug shirt -7
803 | ```
804 |
805 | **4)** Print only the second field of the third line, if any, from these input files: `ip.txt`, `sample.txt` and `copyright.txt`. Consider space as the field separator.
806 |
807 | ```bash
808 | ##### add your solution here
809 | game
810 | day
811 | bla
812 | ```
813 |
814 |
815 |
816 | # Processing multiple records
817 |
818 | **1)** For the input file `sample.txt`, print lines containing `do` only if the previous line is empty and the line before that contains `you`.
819 |
820 | ```bash
821 | ##### add your solution here
822 | Just do-it
823 | Much ado about nothing
824 | ```
825 |
826 | **2)** For the input file `sample.txt`, match lines containing `do` or `not` case insensitively. Each of these terms occur multiple times in the file. The goal is to print only the second occurrences of these terms (independent of each other).
827 |
828 | ```bash
829 | # for reference, here are all the matches
830 | $ grep -i 'do' sample.txt
831 | Just do-it
832 | No doubt you like it too
833 | Much ado about nothing
834 | $ grep -i 'not' sample.txt
835 | Not a bit funny
836 | Much ado about nothing
837 |
838 | ##### add your solution here
839 | No doubt you like it too
840 | Much ado about nothing
841 | ```
842 |
843 | **3)** For the input file `sample.txt`, print the matching lines containing `are` or `bit` as well as `n` lines around the matching lines. The value for `n` is passed to the Ruby command as an environment value.
844 |
845 | ```bash
846 | $ n=1 ##### add your solution here
847 | Good day
848 | How are you
849 |
850 | Today is sunny
851 | Not a bit funny
852 | No doubt you like it too
853 |
854 | # note that the first and last line are empty for this case
855 | $ n=2 ##### add your solution here
856 |
857 | Good day
858 | How are you
859 |
860 | Just do-it
861 |
862 | Today is sunny
863 | Not a bit funny
864 | No doubt you like it too
865 |
866 | ```
867 |
868 | **4)** For the input file `broken.txt`, print all lines between the markers `top` and `bottom`. The first Ruby command shown below doesn't work because it is matching till the end of file as the second marker isn't found. Assume that the input file cannot have two `top` markers without a `bottom` marker appearing in between and vice-versa.
869 |
870 | ```bash
871 | $ cat broken.txt
872 | top
873 | 3.14
874 | bottom
875 | ---
876 | top
877 | 1234567890
878 | bottom
879 | top
880 | Hi there
881 | Have a nice day
882 | Good bye
883 |
884 | # wrong output
885 | $ ruby -ne '$f=false if /bottom/; print if $f; $f=true if /top/' broken.txt
886 | 3.14
887 | 1234567890
888 | Hi there
889 | Have a nice day
890 | Good bye
891 |
892 | # expected output
893 | ##### add your solution here
894 | 3.14
895 | 1234567890
896 | ```
897 |
898 | **5)** For the input file `concat.txt`, extract contents from a line starting with ``%%% `` until but not including the next such line. The block to be extracted is indicated by the variable `n` passed as an environment value.
899 |
900 | ```bash
901 | $ cat concat.txt
902 | %%% addr.txt
903 | How are you
904 | This game is good
905 | Today %%% is sunny
906 | %%% broken.txt
907 | top %%%
908 | 1234567890
909 | bottom
910 | %%% sample.txt
911 | Just %%% do-it
912 | Believe it
913 | %%% mixed_fs.txt
914 | pink blue white yellow
915 | car,mat,ball,basket
916 |
917 | $ n=2 ##### add your solution here
918 | %%% broken.txt
919 | top %%%
920 | 1234567890
921 | bottom
922 | $ n=4 ##### add your solution here
923 | %%% mixed_fs.txt
924 | pink blue white yellow
925 | car,mat,ball,basket
926 | ```
927 |
928 | **6)** For the input file `ruby.md`, replace all occurrences of `ruby` (irrespective of case) with `Ruby`. But, do not replace any matches between ` ```ruby ` and ` ``` ` lines (`ruby` in these markers shouldn't be replaced either). Save the output in `out.md`.
929 |
930 | ```bash
931 | ##### add your solution here, redirect the output to 'out.md'
932 | $ diff -sq out.md expected.md
933 | Files out.md and expected.md are identical
934 | ```
935 |
936 | **7)** Print the last two lines for each of the input files `ip.txt`, `sample.txt` and `table.txt`. Also, add a separator between the results as shown below (note that the separator isn't present at the end of the output). Assume that the input files will have at least two lines.
937 |
938 | ```bash
939 | ##### add your solution here
940 | 12345
941 | You are funny
942 | ---
943 | Much ado about nothing
944 | He he he
945 | ---
946 | blue cake mug shirt -7
947 | yellow banana window shoes 3.14
948 | ```
949 |
950 | **8)** For the input file `lines.txt`, delete the line that comes after a whole line containing `---`. Assume that such lines won't occur consecutively.
951 |
952 | ```bash
953 | $ cat lines.txt
954 | Go There
955 | come on
956 | go there
957 | ---
958 | 2 apples and 5 mangoes
959 | come on!
960 | ---
961 | 2 Apples
962 | COME ON
963 |
964 | ##### add your solution here
965 | Go There
966 | come on
967 | go there
968 | ---
969 | come on!
970 | ---
971 | COME ON
972 | ```
973 |
974 | **9)** For the input file `result.csv`, use `---` to separate entries with the same name in the first column. Assume that the lines with the same first column value will always be next to each other.
975 |
976 | ```bash
977 | $ cat result.csv
978 | Amy,maths,89
979 | Amy,physics,75
980 | Joe,maths,79
981 | John,chemistry,77
982 | John,physics,91
983 | Moe,maths,81
984 | Ravi,physics,84
985 | Ravi,chemistry,70
986 | Yui,maths,92
987 |
988 | ##### add your solution here
989 | Amy,maths,89
990 | Amy,physics,75
991 | ---
992 | Joe,maths,79
993 | ---
994 | John,chemistry,77
995 | John,physics,91
996 | ---
997 | Moe,maths,81
998 | ---
999 | Ravi,physics,84
1000 | Ravi,chemistry,70
1001 | ---
1002 | Yui,maths,92
1003 | ```
1004 |
1005 | **10)** The input file `multisort.csv` has two fields separated by the comma character. Sort this file based on the number of `:` characters in the second field. Use alphabetic order as the tie-breaker if there are multiple lines with the same number of `:` characters in the second field.
1006 |
1007 | ```bash
1008 | $ cat multisort.csv
1009 | papaya,2
1010 | apple,4:5:2
1011 | mango,100
1012 | dark:chocolate,12:32
1013 | cherry,1:2:1:4:2:1
1014 | almond,3:14:6:28
1015 | banana,23:8
1016 |
1017 | ##### add your solution here
1018 | mango,100
1019 | papaya,2
1020 | banana,23:8
1021 | dark:chocolate,12:32
1022 | apple,4:5:2
1023 | almond,3:14:6:28
1024 | cherry,1:2:1:4:2:1
1025 | ```
1026 |
1027 |
1028 |
1029 | # Two file processing
1030 |
1031 | **1)** Use the contents of `match_words.txt` file to display matching lines from `jumbled.txt` and `sample.txt`. The matching criteria is that the second word of lines from these files should match the third word of lines from `match_words.txt`.
1032 |
1033 | ```bash
1034 | $ cat match_words.txt
1035 | %whole(Hello)--{doubt}==ado==
1036 | just,\joint*,concession<=nice
1037 |
1038 | # 'concession' is one of the third words from 'match_words.txt'
1039 | # and second word from 'jumbled.txt'
1040 | ##### add your solution here
1041 | wavering:concession/woof\retailer
1042 | No doubt you like it too
1043 | ```
1044 |
1045 | **2)** Interleave the contents of `secrets.txt` with the contents of a file passed as stdin in the format as shown below.
1046 |
1047 | ```bash
1048 | ##### add your solution here, use 'table.txt' as stdin
1049 | stag area row tick
1050 | brown bread mat hair 42
1051 | ---
1052 | deaf chi rate tall glad
1053 | blue cake mug shirt -7
1054 | ---
1055 | Bi tac toe - 42
1056 | yellow banana window shoes 3.14
1057 | ```
1058 |
1059 | **3)** The file `search_terms.txt` contains one search string per line, and these terms have no regexp metacharacters. Construct a solution that reads this file and displays the search terms (matched case insensitively) that were found in every file passed as the arguments after `search_terms.txt`. Note that these terms should be matched anywhere in the line (so, don't use word boundaries).
1060 |
1061 | ```bash
1062 | $ cat search_terms.txt
1063 | hello
1064 | row
1065 | you
1066 | is
1067 | at
1068 |
1069 | # ip: search_terms.txt jumbled.txt mixed_fs.txt secrets.txt table.txt oops.txt
1070 | ##### add your solution here
1071 | row
1072 | at
1073 |
1074 | # ip: search_terms.txt ip.txt sample.txt oops.txt
1075 | ##### add your solution here
1076 | hello
1077 | you
1078 | is
1079 | ```
1080 |
1081 | **4)** For the input file `ip.txt`, print all lines that contain `are` and the line that comes after such a line, if any. Use the `gets` method to construct the solution.
1082 |
1083 | ```bash
1084 | # note that there shouldn't be an empty line at the end of the output
1085 | ##### add your solution here
1086 | How are you
1087 | This game is good
1088 | You are funny
1089 | ```
1090 |
1091 | **Bonus:** Will `grep -A1 'is' ip.txt` give identical results for your solution with `is` as the search term? If not, why?
1092 |
1093 | **5)** Replace the third to fifth lines of the input file `ip.txt` with the second to fourth lines from the file `para.txt`.
1094 |
1095 | ```bash
1096 | ##### add your solution here
1097 | Hello World
1098 | How are you
1099 | Start working on that
1100 | project you always wanted
1101 | to, do not let it end
1102 | You are funny
1103 | ```
1104 |
1105 | **6)** Insert one line from `jumbled.txt` before every two lines of `copyright.txt`.
1106 |
1107 | ```bash
1108 | ##### add your solution here
1109 | overcoats;furrowing-typeface%pewter##hobby
1110 | bla bla 2015 bla
1111 | blah 2018 blah
1112 | wavering:concession/woof\retailer
1113 | bla bla bla
1114 | copyright: 2018
1115 | ```
1116 |
1117 | **7)** Use the entire contents of `match.txt` to search `error.txt` and replace matching portions with the contents of `jumbled.txt`. Partial lines should NOT be matched.
1118 |
1119 | ```bash
1120 | $ cat match.txt
1121 | print+this
1122 | but not that
1123 | $ cat error.txt
1124 | print+this
1125 | but not that or this
1126 | print+this
1127 | but not that
1128 | if print+this
1129 | but not that
1130 | print+this
1131 | but not that
1132 |
1133 | ##### add your solution here
1134 | print+this
1135 | but not that or this
1136 | overcoats;furrowing-typeface%pewter##hobby
1137 | wavering:concession/woof\retailer
1138 | joint[]seer{intuition}titanic
1139 | if print+this
1140 | but not that
1141 | overcoats;furrowing-typeface%pewter##hobby
1142 | wavering:concession/woof\retailer
1143 | joint[]seer{intuition}titanic
1144 | ```
1145 |
1146 | **8)** Display lines from `scores.csv` by matching the first field based on a list of names from the `names.txt` file. Also, change the output field separator to a space character.
1147 |
1148 | ```bash
1149 | $ cat names.txt
1150 | Lin
1151 | Cy
1152 | Ith
1153 |
1154 | ##### add your solution here
1155 | Lin 78 83 80
1156 | Cy 97 98 95
1157 | Ith 100 100 100
1158 | ```
1159 |
1160 | **9)** The `result.csv` file has three columns — name, subject and mark. The `criteria.txt` file has two columns — name and subject. Match lines from `result.csv` based on the two columns from `criteria.txt` provided the mark column is greater than 80.
1161 |
1162 | ```bash
1163 | $ cat result.csv
1164 | Amy,maths,89
1165 | Amy,physics,75
1166 | Joe,maths,79
1167 | John,chemistry,77
1168 | John,physics,91
1169 | Moe,maths,81
1170 | Ravi,physics,84
1171 | Ravi,chemistry,70
1172 | Yui,maths,92
1173 |
1174 | $ cat criteria.txt
1175 | Amy maths
1176 | John chemistry
1177 | John physics
1178 | Ravi chemistry
1179 | Yui maths
1180 |
1181 | ##### add your solution here
1182 | Amy,maths,89
1183 | John,physics,91
1184 | Yui,maths,92
1185 | ```
1186 |
1187 | **10)** Insert the contents of `hex.txt` before a line matching `cake` of `table.txt`.
1188 |
1189 | ```bash
1190 | ##### add your solution here
1191 | brown bread mat hair 42
1192 | start: 0xA0, func1: 0xA0
1193 | end: 0xFF, func2: 0xB0
1194 | restart: 0xA010, func3: 0x7F
1195 | blue cake mug shirt -7
1196 | yellow banana window shoes 3.14
1197 | ```
1198 |
1199 | **11)** For the input file `ip.txt`, replace lines containing `are` with the contents of `hex.txt`.
1200 |
1201 | ```bash
1202 | ##### add your solution here
1203 | Hello World
1204 | start: 0xA0, func1: 0xA0
1205 | end: 0xFF, func2: 0xB0
1206 | restart: 0xA010, func3: 0x7F
1207 | This game is good
1208 | Today is sunny
1209 | 12345
1210 | start: 0xA0, func1: 0xA0
1211 | end: 0xFF, func2: 0xB0
1212 | restart: 0xA010, func3: 0x7F
1213 | ```
1214 |
1215 |
1216 |
1217 | # Dealing with duplicates
1218 |
1219 | **1)** Retain only the first copy of a line for the input file `lines.txt`. Case should be ignored while comparing the lines. For example, `hi there` and `HI TheRE` should be considered as duplicates.
1220 |
1221 | ```bash
1222 | $ cat lines.txt
1223 | Go There
1224 | come on
1225 | go there
1226 | ---
1227 | 2 apples and 5 mangoes
1228 | come on!
1229 | ---
1230 | 2 Apples
1231 | COME ON
1232 |
1233 | ##### add your solution here
1234 | Go There
1235 | come on
1236 | ---
1237 | 2 apples and 5 mangoes
1238 | come on!
1239 | 2 Apples
1240 | ```
1241 |
1242 | **2)** Retain only the first copy of a line for the input file `twos.txt`. Assume space as the field separator with exactly two fields per line. Compare the lines irrespective of the order of the fields. For example, `hehe haha` and `haha hehe` should be considered as duplicates.
1243 |
1244 | ```bash
1245 | $ cat twos.txt
1246 | hehe haha
1247 | door floor
1248 | haha hehe
1249 | 6;8 3-4
1250 | true blue
1251 | hehe bebe
1252 | floor door
1253 | 3-4 6;8
1254 | tru eblue
1255 | haha hehe
1256 |
1257 | ##### add your solution here
1258 | hehe haha
1259 | door floor
1260 | 6;8 3-4
1261 | true blue
1262 | hehe bebe
1263 | tru eblue
1264 | ```
1265 |
1266 | **3)** For the input file `twos.txt`, display only the unique lines. Assume space as the field separator with exactly two fields per line. Compare the lines irrespective of the order of the fields. For example, `hehe haha` and `haha hehe` should be considered as duplicates.
1267 |
1268 | ```bash
1269 | ##### add your solution here
1270 | true blue
1271 | hehe bebe
1272 | tru eblue
1273 | ```
1274 |
1275 |
--------------------------------------------------------------------------------
/exercises/Exercise_solutions.md:
--------------------------------------------------------------------------------
1 | # Exercise solutions
2 |
3 |
4 |
5 | # One-liner introduction
6 |
7 | **1)** For the input file `ip.txt`, display all lines containing `is`.
8 |
9 | ```bash
10 | $ cat ip.txt
11 | Hello World
12 | How are you
13 | This game is good
14 | Today is sunny
15 | 12345
16 | You are funny
17 |
18 | $ ruby -ne 'print if /is/' ip.txt
19 | This game is good
20 | Today is sunny
21 | ```
22 |
23 | **2)** For the input file `ip.txt`, display the first field of lines *not* containing `y`. Consider space as the field separator for this file.
24 |
25 | ```bash
26 | $ ruby -ane 'puts $F[0] if !/y/' ip.txt
27 | Hello
28 | This
29 | 12345
30 | ```
31 |
32 | **3)** For the input file `ip.txt`, display all lines containing no more than 2 fields.
33 |
34 | ```bash
35 | $ ruby -ane 'print if $F.size <= 2' ip.txt
36 | Hello World
37 | 12345
38 | ```
39 |
40 | **4)** For the input file `ip.txt`, display all lines containing `is` in the second field.
41 |
42 | ```bash
43 | $ ruby -ane 'print if $F[1] =~ /is/' ip.txt
44 | Today is sunny
45 | ```
46 |
47 | **5)** For each line of the input file `ip.txt`, replace the first occurrence of `o` with `0`.
48 |
49 | ```bash
50 | $ ruby -pe 'sub(/o/, "0")' ip.txt
51 | Hell0 World
52 | H0w are you
53 | This game is g0od
54 | T0day is sunny
55 | 12345
56 | Y0u are funny
57 | ```
58 |
59 | **6)** For the input file `table.txt`, calculate and display the product of numbers in the last field of each line. Consider space as the field separator for this file.
60 |
61 | ```bash
62 | $ cat table.txt
63 | brown bread mat hair 42
64 | blue cake mug shirt -7
65 | yellow banana window shoes 3.14
66 |
67 | $ ruby -ane 'BEGIN{p = 1}; p *= $F[-1].to_f; END{puts p}' table.txt
68 | -923.1600000000001
69 | ```
70 |
71 | **7)** Append `.` to all the input lines for the given stdin data.
72 |
73 | ```bash
74 | # can also use: ruby -lne 'print "#{$_}."'
75 | $ printf 'last\nappend\nstop\ntail\n' | ruby -pe 'sub(/$/, ".")'
76 | last.
77 | append.
78 | stop.
79 | tail.
80 | ```
81 |
82 | **8)** Use contents of the `s` variable to display matching lines from the input file `ip.txt`. Assume that `s` doesn't have any regexp metacharacters. Construct the solution such that there's at least one word character immediately preceding the contents of the `s` variable.
83 |
84 | ```bash
85 | $ s='is'
86 |
87 | # can also use: ruby -sne 'print if /\B#{$r}/' -- -r="$s" ip.txt
88 | $ r="$s" ruby -ne 'print if /\B#{ENV["r"]}/' ip.txt
89 | This game is good
90 | ```
91 |
92 | **9)** Use `system` to display the contents of the filename present in the second field of the given input line. Consider space as the field separator.
93 |
94 | ```bash
95 | $ s='report.log ip.txt sorted.txt'
96 | $ echo "$s" | ruby -ane 'system("cat #{$F[1]}")'
97 | Hello World
98 | How are you
99 | This game is good
100 | Today is sunny
101 | 12345
102 | You are funny
103 |
104 | $ s='power.txt table.txt'
105 | $ echo "$s" | ruby -ane 'system("cat #{$F[1]}")'
106 | brown bread mat hair 42
107 | blue cake mug shirt -7
108 | yellow banana window shoes 3.14
109 | ```
110 |
111 |
112 |
113 | # Line processing
114 |
115 | **1)** For the given input, display except the third line.
116 |
117 | ```bash
118 | # can also use: ruby -ne 'print if $. != 3'
119 | $ seq 34 37 | ruby -pe 'next if $. == 3'
120 | 34
121 | 35
122 | 37
123 | ```
124 |
125 | **2)** Display only the fourth, fifth, sixth and seventh lines for the given input.
126 |
127 | ```bash
128 | $ seq 65 78 | ruby -ne 'print if 4..7'
129 | 68
130 | 69
131 | 70
132 | 71
133 | ```
134 |
135 | **3)** For the input file `ip.txt`, replace all occurrences of `are` with `are not` and `is` with `is not` only from line number **4** till the end of file. Also, only the lines that were changed should be displayed in the output.
136 |
137 | ```bash
138 | $ cat ip.txt
139 | Hello World
140 | How are you
141 | This game is good
142 | Today is sunny
143 | 12345
144 | You are funny
145 |
146 | # can also use: $_.gsub!(/(are|is)\K/, " not")
147 | $ ruby -ne 'print if $. >= 4 && $_.gsub!(/are|is/, "\\0 not")' ip.txt
148 | Today is not sunny
149 | You are not funny
150 | ```
151 |
152 | **4)** For the given stdin, display only the first three lines. Avoid processing lines that are not relevant.
153 |
154 | ```bash
155 | $ seq 14 25 | ruby -pe 'exit if $. > 3'
156 | 14
157 | 15
158 | 16
159 | ```
160 |
161 | **5)** For the input file `ip.txt`, display all lines from the start of the file till the first occurrence of `game`.
162 |
163 | ```bash
164 | $ ruby -ne 'print; exit if /game/' ip.txt
165 | Hello World
166 | How are you
167 | This game is good
168 | ```
169 |
170 | **6)** For the input file `ip.txt`, display all lines that contain `is` but not `good`.
171 |
172 | ```bash
173 | $ ruby -ne 'print if /is/ && !/good/' ip.txt
174 | Today is sunny
175 | ```
176 |
177 | **7)** For the input file `ip.txt`, extract the word before the whole word `is` as well as the word after it. If such a match is found, display the two words around `is` in reversed order. For example, `hi;1 is--234 bye` should be converted to `234:1`. Assume that the whole word `is` will not be present more than once in a single line.
178 |
179 | ```bash
180 | # can also use: ruby -ne 'print if $_.sub!(/.*?(\w+)\W+is\W+(\w+).*/, "\\2:\\1")'
181 | $ ruby -ne 'puts "#{$2}:#{$1}" if /(\w+)\W+is\W+(\w+)/' ip.txt
182 | good:game
183 | sunny:Today
184 | ```
185 |
186 | **8)** For the input file `hex.txt`, replace all occurrences of `0xA0` with `0x50` and `0xFF` with `0x7F`.
187 |
188 | ```bash
189 | $ cat hex.txt
190 | start: 0xA0, func1: 0xA0
191 | end: 0xFF, func2: 0xB0
192 | restart: 0xA010, func3: 0x7F
193 |
194 | $ ruby -pe 'gsub(/0xA0/, "0x50"); gsub(/0xFF/, "0x7F")' hex.txt
195 | start: 0x50, func1: 0x50
196 | end: 0x7F, func2: 0xB0
197 | restart: 0x5010, func3: 0x7F
198 | ```
199 |
200 | **9)** For the input file `text.txt`, replace all occurrences of `in` with `an` and write back the changes to `text.txt` itself. The original contents should get saved to `text.txt.orig`.
201 |
202 | ```bash
203 | $ cat text.txt
204 | can ran want plant
205 | tin fin fit mine line
206 |
207 | $ ruby -i.orig -pe 'gsub(/in/, "an")' text.txt
208 |
209 | $ cat text.txt
210 | can ran want plant
211 | tan fan fit mane lane
212 | $ cat text.txt.orig
213 | can ran want plant
214 | tin fin fit mine line
215 | ```
216 |
217 | **10)** For the input file `text.txt`, replace all occurrences of `an` with `in` and write back the changes to `text.txt` itself. Do not create backups for this exercise. Note that you should have solved the previous exercise before starting this one.
218 |
219 | ```bash
220 | $ cat text.txt
221 | can ran want plant
222 | tan fan fit mane lane
223 |
224 | $ ruby -i -pe 'gsub(/an/, "in")' text.txt
225 |
226 | $ cat text.txt
227 | cin rin wint plint
228 | tin fin fit mine line
229 | $ diff text.txt text.txt.orig
230 | 1c1
231 | < cin rin wint plint
232 | ---
233 | > can ran want plant
234 | ```
235 |
236 | **11)** Find the starting index of first occurrence of `is` or `the` or `was` or `to` for each input line of the file `idx.txt`. Assume that every input line will match at least one of these terms.
237 |
238 | ```bash
239 | $ cat idx.txt
240 | match after the last newline character
241 | and then you want to test
242 | this is good bye then
243 | you were there to see?
244 |
245 | $ ruby -ne 'puts $_.index(/is|the|was|to/)' idx.txt
246 | 12
247 | 4
248 | 2
249 | 9
250 | ```
251 |
252 | **12)** Display all lines containing `[4]*` for the given stdin data.
253 |
254 | ```bash
255 | $ printf '2.3/[4]*6\n2[4]5\n5.3-[4]*9\n' | ruby -ne 'print if $_.include?("[4]*")'
256 | 2.3/[4]*6
257 | 5.3-[4]*9
258 | ```
259 |
260 | **13)** For the given input string, change all lowercase alphabets to `x` only for words starting with `m`.
261 |
262 | ```bash
263 | $ s='ma2T3a a2p kite e2e3m meet'
264 |
265 | $ echo "$s" | ruby -pe 'gsub(/\bm\w*+/) {$&.tr("a-z", "x")}'
266 | xx2T3x a2p kite e2e3m xxxx
267 | ```
268 |
269 | **14)** For the input file `ip.txt`, delete all characters other than lowercase vowels and the newline character. Perform this transformation only between a line containing `you` up to line number `4` (inclusive).
270 |
271 | ```bash
272 | $ ruby -pe '$_.tr!("^aeiou\n", "") if /you/..4' ip.txt
273 | Hello World
274 | oaeou
275 | iaeioo
276 | oaiu
277 | 12345
278 | You are funny
279 | ```
280 |
281 | **15)** For the input file `sample.txt`, display from the start of the file till the first occurrence of `are`, excluding the matching line.
282 |
283 | ```bash
284 | $ cat sample.txt
285 | Hello World
286 |
287 | Good day
288 | How are you
289 |
290 | Just do-it
291 | Believe it
292 |
293 | Today is sunny
294 | Not a bit funny
295 | No doubt you like it too
296 |
297 | Much ado about nothing
298 | He he he
299 |
300 | $ ruby -pe 'exit if /are/' sample.txt
301 | Hello World
302 |
303 | Good day
304 | ```
305 |
306 | **16)** For the input file `sample.txt`, display from the last occurrence of `do` till the end of the file.
307 |
308 | ```bash
309 | $ tac sample.txt | ruby -ne 'print; exit if /do/' | tac
310 | Much ado about nothing
311 | He he he
312 | ```
313 |
314 | **17)** For the input file `sample.txt`, display from the 9th line till a line containing `you`.
315 |
316 | ```bash
317 | $ ruby -ne 'print if 9../you/' sample.txt
318 | Today is sunny
319 | Not a bit funny
320 | No doubt you like it too
321 | ```
322 |
323 | **18)** Display only the odd numbered lines from `ip.txt`.
324 |
325 | ```bash
326 | $ ruby -ne 'print if $.%2==1' ip.txt
327 | Hello World
328 | This game is good
329 | 12345
330 | ```
331 |
332 | **19)** For the `table.txt` file, print only the line number for lines containing `air` or `win`.
333 |
334 | ```bash
335 | $ cat table.txt
336 | brown bread mat hair 42
337 | blue cake mug shirt -7
338 | yellow banana window shoes 3.14
339 |
340 | $ ruby -ne 'puts $. if /air|win/' table.txt
341 | 1
342 | 3
343 | ```
344 |
345 | **20)** For the input file `table.txt`, calculate the sum of numbers in the last column, excluding the second line.
346 |
347 | ```bash
348 | $ ruby -ane 'BEGIN{s=0}; s += $F[-1].to_f if $.!=2; END{puts s}' table.txt
349 | 45.14
350 | ```
351 |
352 | **21)** Print the second and fourth line for every block of five lines.
353 |
354 | ```bash
355 | # can also use: ruby -ne 'print if [2, 4].include?($.%5)'
356 | $ seq 15 | ruby -ne 'print if $.%5 == 2 || $.%5 == 4'
357 | 2
358 | 4
359 | 7
360 | 9
361 | 12
362 | 14
363 | ```
364 |
365 | **22)** For the input file `ip.txt`, display all lines containing `e` or `u` but not both.
366 |
367 | ```bash
368 | $ ruby -ne 'print if (/e/ && !/u/) || (!/e/ && /u/)' ip.txt
369 | Hello World
370 | This game is good
371 | Today is sunny
372 | ```
373 |
374 |
375 |
376 | # Field separators
377 |
378 | **1)** For the input file `brackets.txt`, extract only the contents between `()` or `)(` from each input line. Assume that `()` characters will be present only once every line.
379 |
380 | ```bash
381 | $ cat brackets.txt
382 | foo blah blah(ice) 123 xyz$
383 | (almond-pista) choco
384 | yo )yoyo( yo
385 |
386 | $ ruby -F'[()]' -ane 'puts $F[1]' brackets.txt
387 | ice
388 | almond-pista
389 | yoyo
390 | ```
391 |
392 | **2)** For the input file `scores.csv`, extract `Name` and `Physics` fields in the format shown below.
393 |
394 | ```bash
395 | $ cat scores.csv
396 | Name,Maths,Physics,Chemistry
397 | Blue,67,46,99
398 | Lin,78,83,80
399 | Er,56,79,92
400 | Cy,97,98,95
401 | Ort,68,72,66
402 | Ith,100,100,100
403 |
404 | $ ruby -F, -ane 'puts $F.values_at(0,2) * ":"' scores.csv
405 | Name:Physics
406 | Blue:46
407 | Lin:83
408 | Er:79
409 | Cy:98
410 | Ort:72
411 | Ith:100
412 | ```
413 |
414 | **3)** For the input file `scores.csv`, display names of those who've scored above `70` in Maths.
415 |
416 | ```bash
417 | $ ruby -F, -ane 'puts $F[0] if $F[1].to_i > 70' scores.csv
418 | Lin
419 | Cy
420 | Ith
421 | ```
422 |
423 | **4)** Display the number of word characters for the given inputs. Word definition here is same as used in regular expressions. Can you construct a solution with `gsub` and one without the substitution functions?
424 |
425 | ```bash
426 | # solve using gsub
427 | $ echo 'hi there' | ruby -ne 'puts gsub(/\W+/, "").size'
428 | 7
429 |
430 | # solve without using the substitution functions
431 | $ echo 'u-no;co%."(do_12:as' | ruby -ne 'puts $_.scan(/\w/).size'
432 | 12
433 | ```
434 |
435 | **5)** For the input file `quoted.txt`, extract the sequence of characters surrounded by double quotes and display them in the format shown below.
436 |
437 | ```bash
438 | $ cat quoted.txt
439 | 1 "grape" and "mango" and "guava"
440 | ("c 1""d""a-2""b")
441 |
442 | $ ruby -ne 'puts $_.scan(/"[^"]+"/).sort * ","' quoted.txt
443 | "grape","guava","mango"
444 | "a-2","b","c 1","d"
445 | ```
446 |
447 | **6)** Display only the third and fifth characters from each input line.
448 |
449 | ```bash
450 | $ printf 'restore\ncat one\ncricket' | ruby -lne 'print $_[2], $_[4]'
451 | so
452 | to
453 | ik
454 | ```
455 |
456 | **7)** Transform the given input file `fw.txt` to get the output as shown below. If the second field is empty (i.e. contains only space characters), replace it with `NA`.
457 |
458 | ```bash
459 | $ cat fw.txt
460 | 1.3 rs 90 0.134563
461 | 3.8 6
462 | 5.2 ye 8.2387
463 | 4.2 kt 32 45.1
464 |
465 | $ ruby -ne 'a = $_.unpack("a3x2a2x7a*");
466 | a[1] = "NA" if a[1] == " ";
467 | puts a * ","' fw.txt
468 | 1.3,rs,0.134563
469 | 3.8,NA,6
470 | 5.2,ye,8.2387
471 | 4.2,kt,45.1
472 | ```
473 |
474 | **8)** For the input file `scores.csv`, display the header as well as any row which contains `b` or `t` (irrespective of case) in the first field.
475 |
476 | ```bash
477 | $ ruby -F, -ane 'print if $.==1 || $F[0].match?(/[bt]/i)' scores.csv
478 | Name,Maths,Physics,Chemistry
479 | Blue,67,46,99
480 | Ort,68,72,66
481 | Ith,100,100,100
482 | ```
483 |
484 | **9)** Extract all whole words containing `42` but not at the edge of a word. Assume a word cannot contain `42` more than once.
485 |
486 | ```bash
487 | $ s='hi42bye nice1423 bad42 cool_42a 42fake'
488 | $ echo "$s" | ruby -ne 'puts $_.scan(/\w+42\w+/)'
489 | hi42bye
490 | nice1423
491 | cool_42a
492 | ```
493 |
494 | **10)** For the input file `scores.csv`, add another column named **GP** which is calculated out of 100 by giving 50% weightage to Maths and 25% each for Physics and Chemistry.
495 |
496 | ```bash
497 | $ ruby -F, -lane '$F.append($.==1 ? "GP" : ($F[1].to_f/2 + ($F[2].to_f+$F[3].to_f)/4));
498 | puts $F * ","' scores.csv
499 | Name,Maths,Physics,Chemistry,GP
500 | Blue,67,46,99,69.75
501 | Lin,78,83,80,79.75
502 | Er,56,79,92,70.75
503 | Cy,97,98,95,96.75
504 | Ort,68,72,66,68.5
505 | Ith,100,100,100,100.0
506 | ```
507 |
508 | **11)** For the input file `mixed_fs.txt`, retain only the first two fields from each input line. The input and output field separators should be space for first two lines and `,` for the rest of the lines.
509 |
510 | ```bash
511 | $ cat mixed_fs.txt
512 | rose lily jasmine tulip
513 | pink blue white yellow
514 | car,mat,ball,basket
515 | light green,brown,black,purple
516 | apple,banana,cherry
517 |
518 | $ ruby -ne 'f = $.<3? " " : ","; puts $_.split(f)[0..1] * f' mixed_fs.txt
519 | rose lily
520 | pink blue
521 | car,mat
522 | light green,brown
523 | apple,banana
524 | ```
525 |
526 | **12)** For the given space separated numbers, filter only numbers in the range `20` to `1000` (inclusive).
527 |
528 | ```bash
529 | $ s='20 -983 5 756 634223 1000'
530 |
531 | $ echo "$s" | ruby -ane 'puts $F.map(&:to_i).grep(20..1000) * " "'
532 | 20 756 1000
533 | ```
534 |
535 | **13)** For the given space separated words, randomize the order of characters for each word.
536 |
537 | ```bash
538 | $ s='this is a sample sentence'
539 |
540 | # sample randomized output shown here, could be different for you
541 | $ echo "$s" | ruby -ane 'puts $F.map {|s| s.chars.shuffle * ""} * " "'
542 | shti si a salemp sneentce
543 | ```
544 |
545 | **14)** For the given input file `words.txt`, filter all lines containing characters in ascending and descending order.
546 |
547 | ```bash
548 | $ cat words.txt
549 | bot
550 | art
551 | are
552 | boat
553 | toe
554 | flee
555 | reed
556 |
557 | # ascending order
558 | $ ruby -lne 'print if $_ == $_.chars.sort * ""' words.txt
559 | bot
560 | art
561 |
562 | # descending order
563 | $ ruby -lne 'print if $_ == $_.chars.sort.reverse * ""' words.txt
564 | toe
565 | reed
566 | ```
567 |
568 | **15)** For the given space separated words, extract the three longest words.
569 |
570 | ```bash
571 | $ s='I bought two bananas and three mangoes'
572 |
573 | $ echo "$s" | ruby -ane 'puts $F.max_by(3) {_1.size}'
574 | mangoes
575 | bananas
576 | bought
577 | ```
578 |
579 | **16)** Convert the contents of `split.txt` as shown below.
580 |
581 | ```bash
582 | $ cat split.txt
583 | apple,1:2:5,mango
584 | wry,4,look
585 | pencil,3:8,paper
586 |
587 | $ ruby -F, -lane '$F[1].split(/:/).each {puts [$F[0],_1,$F[2]] * ","}' split.txt
588 | apple,1,mango
589 | apple,2,mango
590 | apple,5,mango
591 | wry,4,look
592 | pencil,3,paper
593 | pencil,8,paper
594 | ```
595 |
596 | **17)** For the input file `varying_fields.txt`, construct a solution to get the output shown below.
597 |
598 | ```bash
599 | $ cat varying_fields.txt
600 | hi,bye,there,was,here,to
601 | 1,2,3,4,5
602 |
603 | $ ruby -F, -ane 'puts $F.values_at(0,1,-1) * ":"' varying_fields.txt
604 | hi:bye:to
605 | 1:2:5
606 | ```
607 |
608 | **18)** The `fields.txt` file has fields separated by the `:` character. Delete `:` and the last field if there is a digit character anywhere before the last field. Solution shouldn't use the substitution functions.
609 |
610 | ```bash
611 | $ cat fields.txt
612 | 42:cat
613 | twelve:a2b
614 | we:be:he:0:a:b:bother
615 | apple:banana-42:cherry:
616 | dragon:unicorn:centaur
617 |
618 | $ ruby -F: -ane '$F.pop if /\d.*:/; puts $F * ":"' fields.txt
619 | 42
620 | twelve:a2b
621 | we:be:he:0:a:b
622 | apple:banana-42:cherry
623 | dragon:unicorn:centaur
624 | ```
625 |
626 | **19)** The sample string shown below uses `cat` as the field separator (irrespective of case). Use space as the output field separator and add `42` as the last field.
627 |
628 | ```bash
629 | $ s='applecatfigCaT12345cAtbanana'
630 |
631 | $ echo "$s" | ruby -F'(?i)cat' -lane 'puts [$F, 42] * " "'
632 | apple fig 12345 banana 42
633 | ```
634 |
635 | **20)** For the input file `sample.txt`, filter lines containing 5 or more lowercase vowels.
636 |
637 | ```bash
638 | # can also use: ruby -ne 'print if /([aeiou][^aeiou]*+){5}/' sample.txt
639 | $ ruby -F'[aeiou]' -ane 'print if $F.size > 5' sample.txt
640 | How are you
641 | Believe it
642 | No doubt you like it too
643 | Much ado about nothing
644 | ```
645 |
646 |
647 |
648 | # Record separators
649 |
650 | **1)** The input file `jumbled.txt` consists of words separated by various delimiters. Display the last four words that contain `an` or `at` or `in` or `it`, one per line.
651 |
652 | ```bash
653 | $ cat jumbled.txt
654 | overcoats;furrowing-typeface%pewter##hobby
655 | wavering:concession/woof\retailer
656 | joint[]seer{intuition}titanic
657 |
658 | $ ruby -0777 -ne 'puts $_.scan(/\w*[ai][nt]\w*/)[-4..]' jumbled.txt
659 | wavering
660 | joint
661 | intuition
662 | titanic
663 | ```
664 |
665 | **2)** Emulate `paste -sd,` with Ruby.
666 |
667 | ```bash
668 | # this command joins all input lines with the ',' character
669 | $ paste -sd, ip.txt
670 | Hello World,How are you,This game is good,Today is sunny,12345,You are funny
671 |
672 | # make sure there's no ',' at the end of the line
673 | # and that there's a newline character at the end of the line
674 | $ ruby -lpe '$\ = $<.eof ? "\n" : ","' ip.txt
675 | Hello World,How are you,This game is good,Today is sunny,12345,You are funny
676 |
677 | # if there's only one line in input, again make sure there's no trailing ','
678 | # and that there's a newline character at the end of the line
679 | $ printf 'fig' | paste -sd,
680 | fig
681 | $ printf 'fig' | ruby -lpe '$\ = $<.eof ? "\n" : ","'
682 | fig
683 | ```
684 |
685 | **3)** For the input file `sample.txt`, extract all paragraphs having words starting with `do`.
686 |
687 | ```bash
688 | $ cat sample.txt
689 | Hello World
690 |
691 | Good day
692 | How are you
693 |
694 | Just do-it
695 | Believe it
696 |
697 | Today is sunny
698 | Not a bit funny
699 | No doubt you like it too
700 |
701 | Much ado about nothing
702 | He he he
703 |
704 | # note that there's no extra empty line at the end of the output
705 | $ ruby -l -00 -ne '(print $s, $_; $s="\n") if /\bdo/' sample.txt
706 | Just do-it
707 | Believe it
708 |
709 | Today is sunny
710 | Not a bit funny
711 | No doubt you like it too
712 | ```
713 |
714 | **4)** For the input file `sample.txt`, change each paragraph to a single line by joining lines using `.` and a space character as the separator. Also, add a final `.` to each paragraph.
715 |
716 | ```bash
717 | # note that there's no extra empty line at the end of the output
718 | $ ruby -F'\n' -00 -lane '$\ = $<.eof ? ".\n" : ".\n\n"; print $F * ". "' sample.txt
719 | Hello World.
720 |
721 | Good day. How are you.
722 |
723 | Just do-it. Believe it.
724 |
725 | Today is sunny. Not a bit funny. No doubt you like it too.
726 |
727 | Much ado about nothing. He he he.
728 | ```
729 |
730 | **5)** For the given input, use `;;` as the record separators and `:` as the field separators. Filter records whose second field is greater than `50`.
731 |
732 | ```bash
733 | $ s='mango:100;;apple:25;;grapes:75'
734 |
735 | # note that the output has ;; at the end, not a newline character
736 | $ printf "$s" | ruby -F: -lane 'BEGIN{$/=$\=";;"}; print if $F[1].to_i > 50'
737 | mango:100;;grapes:75;;
738 | ```
739 |
740 | **6)** The input file `f1.txt` has varying amount of empty lines between the records. Change them to be always two empty lines. Also, remove empty lines at the start and end of the file.
741 |
742 | ```bash
743 | $ ruby -l -00 -ne 'print $s, $_; $s="\n\n"' f1.txt
744 | hello
745 |
746 |
747 | world
748 |
749 |
750 | apple
751 | banana
752 | cherry
753 |
754 |
755 | tea coffee
756 | chocolate
757 | ```
758 |
759 | **7)** The sample string shown below uses `cat` as the record separator. Display only the even numbered records separated by a single empty line.
760 |
761 | ```bash
762 | $ s='applecatfigcat12345catbananacatguava:cat:mangocat3'
763 | $ echo "$s" | ruby -lne 'BEGIN{$/ = "cat"}; (print $s, $_; $s="\n") if $.%2==0'
764 | fig
765 |
766 | banana
767 |
768 | :mango
769 | ```
770 |
771 |
772 |
773 | # Multiple file input
774 |
775 | **1)** Print the last field of first two lines for the input files `table.txt` and `ip.txt`. Assume space as the field separators for these two files. To make the output more informative, print filenames and a separator as shown in the output below. Assume that the input files will have at least two lines.
776 |
777 | ```bash
778 | # table.txt ip.txt are passed as file inputs
779 | $ ruby -lane 'puts ">#{ARGF.filename}<" if $.==1;
780 | puts $F[-1];
781 | (puts "----------"; ARGF.close) if $.==2' table.txt ip.txt
782 | >table.txt<
783 | 42
784 | -7
785 | ----------
786 | >ip.txt<
787 | World
788 | you
789 | ----------
790 | ```
791 |
792 | **2)** For the input files `sample.txt`, `secrets.txt`, `ip.txt` and `table.txt`, display only the names of files that contain `at` or `fun` in the third field. Assume space as the field separator.
793 |
794 | ```bash
795 | # you'll need $F[2] && $F[2].match?(/at|fun/) if you want to use the match? method
796 | $ ruby -lane '(puts ARGF.filename; ARGF.close) if $F[2] =~ /at|fun/
797 | ' sample.txt secrets.txt ip.txt table.txt
798 | secrets.txt
799 | ip.txt
800 | table.txt
801 | ```
802 |
803 | **3)** Print the first two lines from the input files `ip.txt`, `sample.txt` and `table.txt`. Also, add a separator between the results as shown below (note that the separator isn't present at the end of the output). Assume that the input files will have at least two lines.
804 |
805 | ```bash
806 | $ ruby -pe 'print $s if $.==1; (ARGF.close; $s="---\n") if $.==2
807 | ' ip.txt sample.txt table.txt
808 | Hello World
809 | How are you
810 | ---
811 | Hello World
812 |
813 | ---
814 | brown bread mat hair 42
815 | blue cake mug shirt -7
816 | ```
817 |
818 | **4)** Print only the second field of the third line, if any, from these input files: `ip.txt`, `sample.txt` and `copyright.txt`. Consider space as the field separator.
819 |
820 | ```bash
821 | $ ruby -ane 'puts $F[1] if $.==3; ARGF.close if ARGF.eof' ip.txt sample.txt copyright.txt
822 | game
823 | day
824 | bla
825 | ```
826 |
827 |
828 |
829 | # Processing multiple records
830 |
831 | **1)** For the input file `sample.txt`, print lines containing `do` only if the previous line is empty and the line before that contains `you`.
832 |
833 | ```bash
834 | $ ruby -lne 'print if $p2=~/you/ && $p1==""; $p2=$p1; $p1=$_' sample.txt
835 | Just do-it
836 | Much ado about nothing
837 | ```
838 |
839 | **2)** For the input file `sample.txt`, match lines containing `do` or `not` case insensitively. Each of these terms occur multiple times in the file. The goal is to print only the second occurrences of these terms (independent of each other).
840 |
841 | ```bash
842 | # for reference, here are all the matches
843 | $ grep -i 'do' sample.txt
844 | Just do-it
845 | No doubt you like it too
846 | Much ado about nothing
847 | $ grep -i 'not' sample.txt
848 | Not a bit funny
849 | Much ado about nothing
850 |
851 | $ ruby -ne 'BEGIN{d=n=0};
852 | print if /do/i && (d+=1)==2;
853 | print if /not/i && (n+=1)==2' sample.txt
854 | No doubt you like it too
855 | Much ado about nothing
856 | ```
857 |
858 | **3)** For the input file `sample.txt`, print the matching lines containing `are` or `bit` as well as `n` lines around the matching lines. The value for `n` is passed to the Ruby command as an environment value.
859 |
860 | ```bash
861 | $ n=1 ruby -e 'BEGIN{n=ENV["n"].to_i}; ip=readlines;
862 | ip.each_with_index { |s, i| c=i-n; c=0 if c<0;
863 | puts ip[c..i+n] if s.match?(/are|bit/) }' sample.txt
864 | Good day
865 | How are you
866 |
867 | Today is sunny
868 | Not a bit funny
869 | No doubt you like it too
870 |
871 | # note that the first and last line are empty for this case
872 | $ n=2 ruby -e 'BEGIN{n=ENV["n"].to_i}; ip=readlines;
873 | ip.each_with_index { |s, i| c=i-n; c=0 if c<0;
874 | puts ip[c..i+n] if s.match?(/are|bit/) }' sample.txt
875 |
876 | Good day
877 | How are you
878 |
879 | Just do-it
880 |
881 | Today is sunny
882 | Not a bit funny
883 | No doubt you like it too
884 |
885 | ```
886 |
887 | **4)** For the input file `broken.txt`, print all lines between the markers `top` and `bottom`. The first Ruby command shown below doesn't work because it is matching till the end of file as the second marker isn't found. Assume that the input file cannot have two `top` markers without a `bottom` marker appearing in between and vice-versa.
888 |
889 | ```bash
890 | $ cat broken.txt
891 | top
892 | 3.14
893 | bottom
894 | ---
895 | top
896 | 1234567890
897 | bottom
898 | top
899 | Hi there
900 | Have a nice day
901 | Good bye
902 |
903 | # wrong output
904 | $ ruby -ne '$f=false if /bottom/; print if $f; $f=true if /top/' broken.txt
905 | 3.14
906 | 1234567890
907 | Hi there
908 | Have a nice day
909 | Good bye
910 |
911 | # expected output
912 | $ tac broken.txt | ruby -ne '$f=false if /top/; print if $f; $f=true if /bottom/' | tac
913 | 3.14
914 | 1234567890
915 | ```
916 |
917 | **5)** For the input file `concat.txt`, extract contents from a line starting with ``%%% `` until but not including the next such line. The block to be extracted is indicated by the variable `n` passed as an environment value.
918 |
919 | ```bash
920 | $ cat concat.txt
921 | %%% addr.txt
922 | How are you
923 | This game is good
924 | Today %%% is sunny
925 | %%% broken.txt
926 | top %%%
927 | 1234567890
928 | bottom
929 | %%% sample.txt
930 | Just %%% do-it
931 | Believe it
932 | %%% mixed_fs.txt
933 | pink blue white yellow
934 | car,mat,ball,basket
935 |
936 | $ n=2 ruby -ne 'BEGIN{n=ENV["n"].to_i; c=0};
937 | c+=1 if /\A%%% /; print if c==n' concat.txt
938 | %%% broken.txt
939 | top %%%
940 | 1234567890
941 | bottom
942 | $ n=4 ruby -ne 'BEGIN{n=ENV["n"].to_i; c=0};
943 | c+=1 if /\A%%% /; print if c==n' concat.txt
944 | %%% mixed_fs.txt
945 | pink blue white yellow
946 | car,mat,ball,basket
947 | ```
948 |
949 | **6)** For the input file `ruby.md`, replace all occurrences of `ruby` (irrespective of case) with `Ruby`. But, do not replace any matches between ` ```ruby ` and ` ``` ` lines (`ruby` in these markers shouldn't be replaced either). Save the output in `out.md`.
950 |
951 | ```bash
952 | # can also use: ruby -pe 'gsub(/ruby/i, "Ruby") if !(/```ruby$/../```$/)'
953 | $ ruby -pe '$f=true if /```ruby$/; gsub(/ruby/i, "Ruby") if !$f;
954 | $f=false if /```$/' ruby.md > out.md
955 |
956 | $ diff -sq out.md expected.md
957 | Files out.md and expected.md are identical
958 | ```
959 |
960 | **7)** Print the last two lines for each of the input files `ip.txt`, `sample.txt` and `table.txt`. Also, add a separator between the results as shown below (note that the separator isn't present at the end of the output). Assume that the input files will have at least two lines.
961 |
962 | ```bash
963 | $ ruby -ne '(print $s,$p,$_; $s="---\n") if ARGF.eof; $p=$_' ip.txt sample.txt table.txt
964 | 12345
965 | You are funny
966 | ---
967 | Much ado about nothing
968 | He he he
969 | ---
970 | blue cake mug shirt -7
971 | yellow banana window shoes 3.14
972 | ```
973 |
974 | **8)** For the input file `lines.txt`, delete the line that comes after a whole line containing `---`. Assume that such lines won't occur consecutively.
975 |
976 | ```bash
977 | $ cat lines.txt
978 | Go There
979 | come on
980 | go there
981 | ---
982 | 2 apples and 5 mangoes
983 | come on!
984 | ---
985 | 2 Apples
986 | COME ON
987 |
988 | $ ruby -ne 'print if $p != "---\n"; $p=$_' lines.txt
989 | Go There
990 | come on
991 | go there
992 | ---
993 | come on!
994 | ---
995 | COME ON
996 | ```
997 |
998 | **9)** For the input file `result.csv`, use `---` to separate entries with the same name in the first column. Assume that the lines with the same first column value will always be next to each other.
999 |
1000 | ```bash
1001 | $ cat result.csv
1002 | Amy,maths,89
1003 | Amy,physics,75
1004 | Joe,maths,79
1005 | John,chemistry,77
1006 | John,physics,91
1007 | Moe,maths,81
1008 | Ravi,physics,84
1009 | Ravi,chemistry,70
1010 | Yui,maths,92
1011 |
1012 | $ ruby -F, -ape 'puts "---" if $.>1 && $p != $F[0]; $p=$F[0]' result.csv
1013 | Amy,maths,89
1014 | Amy,physics,75
1015 | ---
1016 | Joe,maths,79
1017 | ---
1018 | John,chemistry,77
1019 | John,physics,91
1020 | ---
1021 | Moe,maths,81
1022 | ---
1023 | Ravi,physics,84
1024 | Ravi,chemistry,70
1025 | ---
1026 | Yui,maths,92
1027 | ```
1028 |
1029 | **10)** The input file `multisort.csv` has two fields separated by the comma character. Sort this file based on the number of `:` characters in the second field. Use alphabetic order as the tie-breaker if there are multiple lines with the same number of `:` characters in the second field.
1030 |
1031 | ```bash
1032 | $ cat multisort.csv
1033 | papaya,2
1034 | apple,4:5:2
1035 | mango,100
1036 | dark:chocolate,12:32
1037 | cherry,1:2:1:4:2:1
1038 | almond,3:14:6:28
1039 | banana,23:8
1040 |
1041 | $ ruby -e 'puts readlines.sort_by {[_1.split(",")[1].count(":"), _1]}' multisort.csv
1042 | mango,100
1043 | papaya,2
1044 | banana,23:8
1045 | dark:chocolate,12:32
1046 | apple,4:5:2
1047 | almond,3:14:6:28
1048 | cherry,1:2:1:4:2:1
1049 | ```
1050 |
1051 |
1052 |
1053 | # Two file processing
1054 |
1055 | **1)** Use the contents of `match_words.txt` file to display matching lines from `jumbled.txt` and `sample.txt`. The matching criteria is that the second word of lines from these files should match the third word of lines from `match_words.txt`.
1056 |
1057 | ```bash
1058 | $ cat match_words.txt
1059 | %whole(Hello)--{doubt}==ado==
1060 | just,\joint*,concession<=nice
1061 |
1062 | # 'concession' is one of the third words from 'match_words.txt'
1063 | # and second word from 'jumbled.txt'
1064 | $ ruby -rset -ne 'BEGIN{s=Set.new}; words = $_.scan(/\w+/);
1065 | (s.add(words[2]); next) if ARGV.size==2;
1066 | print if s.include?(words[1])
1067 | ' match_words.txt jumbled.txt sample.txt
1068 | wavering:concession/woof\retailer
1069 | No doubt you like it too
1070 | ```
1071 |
1072 | **2)** Interleave the contents of `secrets.txt` with the contents of a file passed as stdin in the format as shown below.
1073 |
1074 | ```bash
1075 | $ ruby -ne 'print $s, $_; puts STDIN.gets; $s="---\n"' 80' criteria.txt result.csv
1224 | Amy,maths,89
1225 | John,physics,91
1226 | Yui,maths,92
1227 | ```
1228 |
1229 | **10)** Insert the contents of `hex.txt` before a line matching `cake` of `table.txt`.
1230 |
1231 | ```bash
1232 | $ ruby -pe 'BEGIN{r = STDIN.read}; print r if /cake/'
1258 |
1259 | # Dealing with duplicates
1260 |
1261 | **1)** Retain only the first copy of a line for the input file `lines.txt`. Case should be ignored while comparing the lines. For example, `hi there` and `HI TheRE` should be considered as duplicates.
1262 |
1263 | ```bash
1264 | $ cat lines.txt
1265 | Go There
1266 | come on
1267 | go there
1268 | ---
1269 | 2 apples and 5 mangoes
1270 | come on!
1271 | ---
1272 | 2 Apples
1273 | COME ON
1274 |
1275 | # same as: ruby -e 'puts readlines.uniq(&:downcase)' lines.txt
1276 | $ ruby -rset -ne 'BEGIN{s=Set.new}; print if s.add?($_.downcase)' lines.txt
1277 | Go There
1278 | come on
1279 | ---
1280 | 2 apples and 5 mangoes
1281 | come on!
1282 | 2 Apples
1283 | ```
1284 |
1285 | **2)** Retain only the first copy of a line for the input file `twos.txt`. Assume space as the field separator with exactly two fields per line. Compare the lines irrespective of the order of the fields. For example, `hehe haha` and `haha hehe` should be considered as duplicates.
1286 |
1287 | ```bash
1288 | $ cat twos.txt
1289 | hehe haha
1290 | door floor
1291 | haha hehe
1292 | 6;8 3-4
1293 | true blue
1294 | hehe bebe
1295 | floor door
1296 | 3-4 6;8
1297 | tru eblue
1298 | haha hehe
1299 |
1300 | # can also use: ruby -rset -lane 'BEGIN{s=Set.new};
1301 | # print if s.add?($F[0] > $F[1] ? $_ : "#{$F[1]} #{$F[0]}")' twos.txt
1302 | $ ruby -e 'puts readlines.uniq {_1.split.sort}' twos.txt
1303 | hehe haha
1304 | door floor
1305 | 6;8 3-4
1306 | true blue
1307 | hehe bebe
1308 | tru eblue
1309 | ```
1310 |
1311 | **3)** For the input file `twos.txt`, display only the unique lines. Assume space as the field separator with exactly two fields per line. Compare the lines irrespective of the order of the fields. For example, `hehe haha` and `haha hehe` should be considered as duplicates.
1312 |
1313 | ```bash
1314 | $ ruby -lane 'BEGIN{h=Hash.new(0)};
1315 | h[$F[0] > $F[1] ? $_ : "#{$F[1]} #{$F[0]}"] += 1;
1316 | END{ h.each_key{|k| puts k if h[k]==1} }' twos.txt
1317 | true blue
1318 | hehe bebe
1319 | tru eblue
1320 | ```
1321 |
1322 |
--------------------------------------------------------------------------------