├── 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 |

Ruby One-Liners Guide ebook cover image

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 | >![info](../images/info.svg) 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 | --------------------------------------------------------------------------------