├── LICENSE ├── README.md ├── Version_changes.md ├── code_snippets ├── Dealing_with_duplicates.sh ├── Field_separators.sh ├── Inplace_file_editing.sh ├── Line_processing.sh ├── Multiple_file_input.sh ├── Oneliner_introduction.sh ├── Perl_rename_command.sh ├── Processing_multiple_records.sh ├── Record_separators.sh ├── Two_file_processing.sh └── Using_modules.sh ├── example_files ├── anchors.txt ├── broken.txt ├── colors.txt ├── colors_1.txt ├── colors_2.txt ├── context.txt ├── dept.txt ├── dept_mark.txt ├── dept_name.txt ├── duplicates.txt ├── eqns.txt ├── f1.txt ├── f2.txt ├── f3.txt ├── fruits.txt ├── greeting.txt ├── ip.txt ├── items.txt ├── marks.txt ├── newline.csv ├── para.txt ├── paths.txt ├── purchases.txt ├── repl.txt ├── report.log ├── role.txt ├── sample.json ├── search.txt ├── t1.txt ├── t2.txt ├── table.txt └── uniform.txt ├── exercises ├── Exercise_solutions.md ├── Exercises.md ├── brackets.txt ├── broken.txt ├── concat.txt ├── copyright.txt ├── criteria.txt ├── error.txt ├── expected.md ├── f1.txt ├── fields.txt ├── fw.txt ├── hex.txt ├── idx.txt ├── ip.txt ├── jumbled.txt ├── lines.txt ├── match.txt ├── match_words.txt ├── mixed_fs.txt ├── names.txt ├── oops.txt ├── out.md ├── para.txt ├── perl.md ├── pets.txt ├── quoted.txt ├── result.csv ├── sample.txt ├── sample.xml ├── scores.csv ├── search_terms.txt ├── secrets.txt ├── split.txt ├── table.txt ├── text.txt ├── twos.txt ├── varying_fields.txt └── words.txt ├── images ├── info.svg ├── perl_oneliners_ls.png └── warning.svg ├── perl_oneliners.md └── sample_chapters └── perl_oneliners_sample.pdf /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Perl One-Liners Guide 2 | 3 | Example based guide for text processing with Perl from the command line. Visit https://youtu.be/_7tP_4T45Ok for a short video about the book. 4 | 5 |

Perl 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/perl-oneliners 19 | * https://leanpub.com/perl-oneliners 20 | * You can also get the book as part of these bundles: 21 | * **All books bundle** bundle from https://learnbyexample.gumroad.com/l/all-books 22 | * Includes all my programming books 23 | * **Magical one-liners** bundle from https://learnbyexample.gumroad.com/l/oneliners or https://leanpub.com/b/oneliners 24 | * See https://learnbyexample.github.io/books/ for a list of other books 25 | 26 | For a preview of the book, see [sample chapters](./sample_chapters/perl_oneliners_sample.pdf). 27 | 28 | The book can also be [viewed as a single markdown file in this repo](./perl_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. 29 | 30 | For the web version of the book, visit https://learnbyexample.github.io/learn_perl_oneliners/ 31 | 32 |
33 | 34 | # Testimonials 35 | 36 | >This is fantastic! 👏 I use Perl one-liners for record and text processing a lot and this will be definitely something I will keep coming back to - I’ve already learned a trick from “Context Matching” (9) 🙂 37 | > 38 | > — [feedback on Linux@lemmy.ml](https://programming.dev/comment/3277968) 39 | 40 |
41 | 42 | # Feedback 43 | 44 | ⚠️ ⚠️ Please DO NOT submit pull requests. Main reason being any modification requires changes in multiple places. 45 | 46 | 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. 47 | 48 | You can reach me via: 49 | 50 | * Issue Manager: [https://github.com/learnbyexample/learn_perl_oneliners/issues](https://github.com/learnbyexample/learn_perl_oneliners/issues) 51 | * E-mail: `echo 'bGVhcm5ieWV4YW1wbGUubmV0QGdtYWlsLmNvbQo=' | base64 --decode` 52 | * Twitter: [https://twitter.com/learn_byexample](https://twitter.com/learn_byexample) 53 | 54 |
55 | 56 | # Table of Contents 57 | 58 | 1) Preface 59 | 2) One-liner introduction 60 | 3) Line processing 61 | 4) In-place file editing 62 | 5) Field separators 63 | 6) Record separators 64 | 7) Using modules 65 | 8) Multiple file input 66 | 9) Processing multiple records 67 | 10) Two file processing 68 | 11) Dealing with duplicates 69 | 12) Perl rename command 70 | 71 |
72 | 73 | # Acknowledgements 74 | 75 | * [Perl documentation](https://perldoc.perl.org/) — manuals, tutorials and examples 76 | * [stackoverflow](https://stackoverflow.com/) and [unix.stackexchange](https://unix.stackexchange.com/) — for getting answers to pertinent questions on Perl and related commands 77 | * [tex.stackexchange](https://tex.stackexchange.com/) — for help on [pandoc](https://github.com/jgm/pandoc/) and `tex` related questions 78 | * [/r/perl/](https://old.reddit.com/r/perl/) — helpful forum 79 | * [canva](https://www.canva.com/) — cover image 80 | * [oxipng](https://github.com/shssoichiro/oxipng), [pngquant](https://pngquant.org/) and [svgcleaner](https://github.com/RazrFalcon/svgcleaner) — optimizing images 81 | * [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 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 | -------------------------------------------------------------------------------- /Version_changes.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | ### 2.0 4 | 5 | * Command version updated to **Perl 5.38.0** 6 | * option `-g` slurps entire file contents 7 | * Many more exercises added 8 | * Long sections split into smaller ones 9 | * In general, many of the examples, exercises, solutions, descriptions and external links were updated/corrected 10 | * Updated Acknowledgements section 11 | * Code snippets related to info/warning sections will now appear as a single block 12 | * Book title changed to **Perl One-Liners Guide** 13 | * New cover image 14 | 15 |
16 | 17 | ### 1.5 18 | 19 | * Added a chapter on Perl `rename` command 20 | * Fixed string examples and description updated for presence of `$`, `@` and `\\` characters 21 | * Examples added/modified based on usage of `while` loop applied to a regexp search with `g` flag active 22 | * Several other changes to improve code snippets, description, etc 23 | 24 |
25 | 26 | ### 1.0 27 | 28 | * First version 29 | -------------------------------------------------------------------------------- /code_snippets/Dealing_with_duplicates.sh: -------------------------------------------------------------------------------- 1 | ## Whole line duplicates 2 | 3 | cat purchases.txt 4 | 5 | perl -ne 'print if !$h{$_}++' purchases.txt 6 | 7 | ## Column wise duplicates 8 | 9 | cat duplicates.txt 10 | 11 | perl -F, -ane 'print if !$h{$F[-1]}++' duplicates.txt 12 | 13 | perl -F, -ane 'print if !$h{$F[0],$F[2]}++' duplicates.txt 14 | 15 | ## Duplicate count 16 | 17 | perl -F, -ane 'print if ++$h{$F[1]} == 2' duplicates.txt 18 | 19 | perl -F, -ane 'print if ++$h{$F[-1]} == 3' duplicates.txt 20 | 21 | tac duplicates.txt | perl -F, -ane 'print if !$h{$F[-1]}++' | tac 22 | 23 | perl -F, -ane '!$#ARGV ? $h{$F[-1]}++ : 24 | $h{$F[-1]}>1 && print' duplicates.txt duplicates.txt 25 | 26 | perl -F, -ane '!$#ARGV ? $h{$F[-1]}++ : 27 | $h{$F[-1]}>2 && print' duplicates.txt duplicates.txt 28 | 29 | perl -F, -ane '!$#ARGV ? $h{$F[2]}++ : 30 | $h{$F[2]}==1 && print' duplicates.txt duplicates.txt 31 | 32 | -------------------------------------------------------------------------------- /code_snippets/Field_separators.sh: -------------------------------------------------------------------------------- 1 | ## Default field separation 2 | 3 | echo ' a b c ' | perl -anE 'say $#F' 4 | 5 | echo ' a b c ' | perl -anE 'say "($F[0])"' 6 | 7 | echo ' a b c ' | perl -anE 'say "($F[-1])"' 8 | 9 | printf ' one \t\f\v two\t\r\tthree \t\r ' | perl -anE 'say scalar @F' 10 | 11 | printf ' one \t\f\v two\t\r\tthree \t\r ' | perl -anE 'say "$F[1]."' 12 | 13 | ## Input field separator 14 | 15 | echo 'goal:amazing:whistle:kwality' | perl -F: -anE 'say "$F[0]\n$F[2]"' 16 | 17 | echo 'one;two;three;four' | perl -F';' -anE 'say $F[2]' 18 | 19 | echo 'load;err_msg--\ant,r2..not' | perl -F'\W+' -anE 'say $F[2]' 20 | 21 | echo 'hi.bye.hello' | perl -F'\.' -anE 'say $F[1]' 22 | 23 | printf 'COOL\nnice car\n' | perl -F'/[aeiou]/i' -anE 'say $#F' 24 | 25 | echo 'goal:amazing:whistle:kwality' | perl -F'/:/,$_,2' -ane 'print $F[1]' 26 | 27 | ## Character-wise separation 28 | 29 | echo 'apple' | perl -F -anE 'say $F[0]' 30 | 31 | echo 'fox:αλεπού' | perl -CS -F -anE 'say @F[4..6]' 32 | 33 | ## Newline character in the last field 34 | 35 | echo 'cat dog' | perl -anE 'say "[$F[-1]]"' 36 | 37 | echo 'cat:dog' | perl -F: -anE 'say "[$F[-1]]"' 38 | 39 | printf 'cat:dog' | perl -F: -anE 'say "[$F[-1]]"' 40 | 41 | echo ' a b c ' | perl -anE 'say $#F' 42 | 43 | echo ':a:b:c:' | perl -F: -anE 'say $#F; say "[$F[-1]]"' 44 | 45 | ## Using the -l option for field splitting 46 | 47 | echo 'cat:dog' | perl -F: -lane 'print "[$F[-1]]"' 48 | 49 | echo ':a:b:c:' | perl -F: -lane 'print scalar @F' 50 | 51 | echo ':a:b:c:' | perl -lne 'print scalar split/:/,$_,-1' 52 | 53 | ## Whitespace and NUL characters in field separation 54 | 55 | s='pick eat rest laugh' 56 | 57 | echo "$s" | perl -F'/t /' -lane 'print $F[0]' 58 | 59 | echo "$s" | perl -F't ' -lane 'print $F[1]' 60 | 61 | echo "$s" | perl -F't\x20' -lane 'print $F[1]' 62 | 63 | echo "$s" | perl -F't[ ]' -lane 'print $F[1]' 64 | 65 | echo "$s" | perl -lne 'print((split /t[ ]/)[1])' 66 | 67 | printf 'aa\0b\0c' | perl -F$'\0' -anE 'say join ",", @F' | cat -v 68 | 69 | printf 'aa\0b\0c' | perl -F'\0' -anE 'say join ",", @F' | cat -v 70 | 71 | ## Output field separator 72 | 73 | perl -lane 'BEGIN{$,=" "} print $F[0], $F[2]' table.txt 74 | 75 | s='Sample123string42with777numbers' 76 | 77 | echo "$s" | perl -F'\d+' -lane 'BEGIN{$,=","} print @F' 78 | 79 | echo 'table' | perl -F -lane 'print @F[0..2]' 80 | 81 | s='Sample123string42with777numbers' 82 | 83 | echo "$s" | perl -F'\d+' -lane 'print join ",", @F' 84 | 85 | s='goal:amazing:whistle:kwality' 86 | 87 | echo "$s" | perl -F: -lane 'print join "-", @F[-1, 1, 0]' 88 | 89 | echo "$s" | perl -F: -lane 'print join "::", @F, 42' 90 | 91 | s='goal:amazing:whistle:kwality' 92 | 93 | echo "$s" | perl -F: -lane 'print "$F[0] $F[2]"' 94 | 95 | echo "$s" | perl -F: -lane 'print "@F[0, 2]"' 96 | 97 | echo "$s" | perl -F: -lane 'BEGIN{$"="-"} print "msg: @F[-1, 1, 0]"' 98 | 99 | ## Manipulating $#F 100 | 101 | s='goal:amazing:whistle:kwality' 102 | 103 | echo "$s" | perl -F: -lane '$#F=1; print join ",", @F' 104 | 105 | echo "$s" | perl -F: -lane '$F[$#F+1]="sea"; print join ":", @F' 106 | 107 | echo "$s" | perl -F: -lane '$F[7]="go"; print join ":", @F' 108 | 109 | echo "1:2:3" | perl -F: -lane '$#F=-1; print "[@F]"' 110 | 111 | cat marks.txt 112 | 113 | perl -anE 'BEGIN{$,="\t"; @g = qw(D C B A S)} 114 | say @F, $.==1 ? "Grade" : $g[$F[-1]/10 - 5]' marks.txt 115 | 116 | ## Defining field contents instead of splitting 117 | 118 | s='Sample123string42with777numbers' 119 | 120 | echo "$s" | perl -nE '@f=/\d+/g; say $f[1]' 121 | 122 | s='coat Bin food tar12 best Apple fig_42' 123 | 124 | echo "$s" | perl -nE 'say join ",", /\b[a-z0-9]+\b/g' 125 | 126 | s='items: "apple" and "mango"' 127 | 128 | echo "$s" | perl -nE '@f=/"[^"]+"/g; say $f[0]' 129 | 130 | perl -nE 'say join "\n", //g if /\bm\w*\b/' table.txt 131 | 132 | perl -nE 'say join "\n", //g if /\bh\w*\b/ || /\bb\w*\b/' table.txt 133 | 134 | perl -nE 'say $& while /\bm\w*\b/g' table.txt 135 | 136 | perl -nE 'say $& while /\b[bh]\w*\b/g' table.txt 137 | 138 | s='eagle,"fox,42",bee,frog' 139 | 140 | echo "$s" | perl -F, -lane 'print $F[1]' 141 | 142 | echo "$s" | perl -lne 'print((/"[^"]+"|[^,]+/g)[1])' 143 | 144 | ## Fixed width processing 145 | 146 | cat items.txt 147 | 148 | perl -lne 'print join ",", unpack "a8a4a6"' items.txt 149 | 150 | perl -lne 'print((unpack "a8a4a6")[1])' items.txt 151 | 152 | perl -lne 'print join ",", unpack "a5x3a3xa6"' items.txt 153 | 154 | printf 'banana\x0050\x00' | perl -nE 'say join ":", unpack "Z*Z*"' 155 | 156 | perl -lne 'print join ",", unpack "a5x3a*"' items.txt 157 | 158 | echo 'b 123 good' | perl -nE 'say substr $_,2,3' 159 | 160 | echo 'b 123 good' | perl -ne 'print substr $_,6' 161 | 162 | echo 'b 123 good' | perl -pe 'substr $_,2,3,"gleam"' 163 | 164 | ## Assorted field processing functions 165 | 166 | s='goal:amazing:42:whistle:kwality:3.14' 167 | 168 | echo "$s" | perl -F: -lane 'print join ":", grep {/i[nts]/} @F' 169 | 170 | echo "$s" | perl -F: -lane 'print scalar grep {!/\d/} @F' 171 | 172 | s='hour hand band mat heated apple hit' 173 | 174 | echo "$s" | perl -lane 'print join "\n", grep {!/^h/ && length()<4} @F' 175 | 176 | echo '20 711 -983 5 21' | perl -lane 'print join ":", grep {$_ > 20} @F' 177 | 178 | perl -lane 'print if 1 >= grep {/r/} @F' table.txt 179 | 180 | s='goal:amazing:42:whistle:kwality:3.14' 181 | 182 | echo "$s" | perl -F: -lane 'print join ":", map {uc} @F' 183 | 184 | echo "$s" | perl -F: -lane 'print join ":", map {/^[gw]/ ? uc : $_} @F' 185 | 186 | echo '23 756 -983 5' | perl -lane 'print join ":", map {$_ ** 2} @F' 187 | 188 | echo 'AaBbCc' | perl -F -lane 'print join " ", map {ord} @F' 189 | 190 | echo 'AaBbCc' | perl -F -lane 'map {$_ = ord} @F; print "@F"' 191 | 192 | echo 'a b c' | perl -lane 'print join ",", map {qq/"$_"/} @F' 193 | 194 | s='hour hand band mat heated pineapple' 195 | 196 | echo "$s" | perl -lane 'print join "\n", map {y/ae/X/r} grep {/^h/} @F' 197 | 198 | echo "$s" | perl -lane 'print join "\n", grep {y/ae/X/; /^h/} @F' 199 | 200 | echo '23 756 -983 5' | perl -lane 'print join " ", sort {$a <=> $b} @F' 201 | 202 | s='floor bat to dubious four' 203 | 204 | echo "$s" | perl -lane 'print join ":", sort @F' 205 | 206 | echo "$s" | perl -lane 'print join ":", sort {length($a) <=> length($b)} @F' 207 | 208 | echo "$s" | perl -lane 'print join ":", sort {length($b) <=> length($a)} @F' 209 | 210 | echo 'dragon' | perl -F -lane 'print reverse sort @F' 211 | 212 | s='try a bad to good i teal by nice how' 213 | 214 | echo "$s" | perl -anE 'say join ":", 215 | sort {length($b) <=> length($a) or $a cmp $b} @F' 216 | 217 | echo "$s" | perl -anE 'say join ":", map {$_->[0]} 218 | sort {$b->[1] <=> $a->[1] or $a->[0] cmp $b->[0]} 219 | map {[$_, length($_)]} @F' 220 | 221 | cat marks.txt 222 | 223 | perl -lane '@i = sort {$F[$b] cmp $F[$a]} 0..$#F if $.==1; 224 | print join "\t", @F[@i]' marks.txt 225 | 226 | -------------------------------------------------------------------------------- /code_snippets/Inplace_file_editing.sh: -------------------------------------------------------------------------------- 1 | ## With backup 2 | 3 | cat colors.txt 4 | 5 | perl -i.bkp -pe 's/blue/-green-/' colors.txt 6 | 7 | cat colors.txt 8 | 9 | cat colors.txt.bkp 10 | 11 | ## Without backup 12 | 13 | cat fruits.txt 14 | 15 | perl -i -pe 's/(..)\1/\U$&/g' fruits.txt 16 | 17 | cat fruits.txt 18 | 19 | ## Multiple files 20 | 21 | cat t1.txt 22 | 23 | cat t2.txt 24 | 25 | perl -i.bkp -pe 's/bad/good/' t1.txt t2.txt 26 | 27 | ls t?.* 28 | 29 | cat t1.txt 30 | 31 | cat t2.txt 32 | 33 | ## Prefix backup name 34 | 35 | ls *colors.txt* 36 | 37 | perl -i'bkp.*' -pe 's/-green-/yellow/' colors.txt 38 | 39 | ls *colors.txt* 40 | 41 | ## Place backups in a different directory 42 | 43 | mkdir backups 44 | 45 | perl -i'backups/*' -pe 's/good/nice/' t1.txt t2.txt 46 | 47 | ls backups/ 48 | 49 | -------------------------------------------------------------------------------- /code_snippets/Line_processing.sh: -------------------------------------------------------------------------------- 1 | ## Regexp based filtering 2 | 3 | cat table.txt 4 | 5 | perl -ne 'print if /ow\b/' table.txt 6 | 7 | perl -ne 'print if !/[ksy]/' table.txt 8 | 9 | cat paths.txt 10 | 11 | perl -ne 'print if /\/home\/ram\//' paths.txt 12 | 13 | perl -ne 'print if m{/home/ram/}' paths.txt 14 | 15 | perl -ne 'print if !m#/home/ram/#' paths.txt 16 | 17 | ## Extracting matched portions 18 | 19 | cat ip.txt 20 | 21 | perl -nE 'say $& if /\b[a-z]\w*[ty]\b/' ip.txt 22 | 23 | perl -nE 'say join "::", @{^CAPTURE} if /(\b[bdp]\w+).*((?1))/i' ip.txt 24 | 25 | perl -nE 'say /^(\w+ ).*?(\d+)$/' table.txt 26 | 27 | perl -nE 'say join ":", /^(\w+).*?(\d+)$/' table.txt 28 | 29 | ## Transliteration 30 | 31 | echo 'Uryyb Jbeyq' | perl -pe 'tr/a-zA-Z/n-za-mN-ZA-M/' 32 | 33 | echo 'apple:123:banana' | perl -pe 'tr/0-9\n/-/c' 34 | 35 | echo 'apple:123:banana' | perl -pe 'tr/0-9\n//cd' 36 | 37 | echo 'APPLE gobbledygook' | perl -pe 'tr|A-Za-z||s' 38 | 39 | echo 'APPLE gobbledygook' | perl -pe 'tr|A-Z|a-z|s' 40 | 41 | perl -ne 'print if tr/b// == 2' table.txt 42 | 43 | s='orange apple appleseed' 44 | 45 | echo "$s" | perl -pe 's#\bapple\b(*SKIP)(*F)|\w+#$&=~tr/a-z/A-Z/r#ge' 46 | 47 | ## Conditional substitution 48 | 49 | printf '1,2,3,4\na,b,c,d\n' | perl -pe 's/,/-/g if !/2/' 50 | 51 | perl -ne 'print s/ark/[$&]/rg if /the/' ip.txt 52 | 53 | perl -ne 'print if s/\bw\w*t\b/{$&}/g' ip.txt 54 | 55 | ## Multiple conditions 56 | 57 | perl -ne 'print if /ark/ && !/sky/' ip.txt 58 | 59 | perl -ane 'print if /\bthe\b/ || $#F == 5' ip.txt 60 | 61 | perl -ne 'print if /s/ xor /m/' table.txt 62 | 63 | ## next 64 | 65 | perl -nE 'if(/\bpar/){print "%% $_"; next} say /s/ ? "X" : "Y"' anchors.txt 66 | 67 | ## exit 68 | 69 | perl -ne 'print; exit if /say/' ip.txt 70 | 71 | perl -pe 'exit if /say/' ip.txt 72 | 73 | tac ip.txt | perl -ne 'print; exit if /an/' | tac 74 | 75 | printf 'sea\neat\ndrop\n' | perl -ne 'print; exit(2) if /at/' 76 | 77 | echo $? 78 | 79 | perl -pE 'exit if /cake/' table.txt 80 | 81 | perl -pE 'exit if /cake/; END{say "bye"}' table.txt 82 | 83 | perl -pE 'BEGIN{say "hi"; exit; say "hello"} END{say "bye"}' table.txt 84 | 85 | ## Line number based processing 86 | 87 | perl -ne 'print if $. == 3' ip.txt 88 | 89 | perl -ne 'print if $. == 2 || $. == 6' ip.txt 90 | 91 | printf 'gates\nnot\nused\n' | perl -pe 'tr/a-z/*/ if $. == 2' 92 | 93 | seq 14 25 | perl -ne 'print if $. >= 10' 94 | 95 | perl -ne 'print if eof' ip.txt 96 | 97 | perl -ne 'print "$.:$_" if eof' ip.txt 98 | 99 | perl -ne 'print if eof' ip.txt table.txt 100 | 101 | seq 3542 4623452 | perl -ne 'if($. == 2452){print; exit}' 102 | 103 | seq 3542 4623452 | perl -ne 'print if $. == 250; if($. == 2452){print; exit}' 104 | 105 | time seq 3542 4623452 | perl -ne 'if($. == 2452){print; exit}' > f1 106 | 107 | time seq 3542 4623452 | perl -ne 'print if $. == 2452' > f2 108 | 109 | rm f1 f2 110 | 111 | ## Range operator 112 | 113 | seq 14 25 | perl -ne 'print if 3..5' 114 | 115 | perl -ne 'print if /to/ .. /pl/' ip.txt 116 | 117 | perl -ne 'print if 6 .. /utter/' ip.txt 118 | 119 | perl -ne 'print if !(/\bba/ .. eof)' ip.txt table.txt 120 | 121 | perl -ne 'print if 7 .. /and/' ip.txt 122 | 123 | perl -ne 'print if 7 ... /and/' ip.txt 124 | 125 | perl -ne 'print if /Banana/ .. /XYZ/' ip.txt 126 | 127 | ## Working with fixed strings 128 | 129 | printf 'int a[5]\nfig\n1+4=5\n' | perl -ne 'print if /a[5]/' 130 | 131 | perl -E 'say "\Qa[5]"' 132 | 133 | printf 'int a[5]\nfig\n1+4=5\n' | perl -ne 'print if /\Qa[5]/' 134 | 135 | printf 'int a[5]\nfig\n1+4=5\n' | perl -pe 's/\Qa[5]/b[12]/' 136 | 137 | echo '$x = $y + $z' | perl -pe 's/\Q$y + $z/100/' 138 | 139 | echo '$x = $y + $z' | fs='$y + $z' perl -pe 's/\Q$ENV{fs}/100/' 140 | 141 | perl -E '$x = q(x\y\\0z); say $x' 142 | 143 | x='x\y\\0z' perl -E 'say $ENV{x}' 144 | 145 | printf 'int a[5]\nfig\n1+4=5\n' | perl -ne 'print if index($_, "a[5]") != -1' 146 | 147 | perl -E '$x=5; say "value of x:\t$x"' 148 | 149 | s='$a = 2 * ($b + $c)' 150 | 151 | echo "$s" | perl -ne 'print if index($_, q/($b + $c)/) != -1' 152 | 153 | echo "$s" | fs='($b + $c)' perl -ne 'print if index($_, $ENV{fs}) != -1' 154 | 155 | cat eqns.txt 156 | 157 | s='a+b' perl -ne 'print if index($_, $ENV{s})==0' eqns.txt 158 | 159 | s='a+b' perl -lne '$pos = length() - length($ENV{s}); 160 | print if index($_, $ENV{s}) == $pos' eqns.txt 161 | 162 | perl -ne '$i = index($_, "="); print if 0 <= $i <= 5' eqns.txt 163 | 164 | s='a+b' perl -ne 'print if index($_, $ENV{s})>=1' eqns.txt 165 | 166 | printf 'a.b\na+b\n' | perl -lne 'print if /^a.b$/' 167 | 168 | printf 'a.b\na+b\n' | perl -lne 'print if $_ eq q/a.b/' 169 | 170 | printf '1 a.b\n2 a+b\n' | perl -lane 'print if $F[1] ne q/a.b/' 171 | 172 | echo 'x+y' | perl -pe 's/\Qx+y/$x+@y/' 173 | 174 | echo 'x+y' | r='$x+@y' perl -pe 's/\Qx+y/$ENV{r}/' 175 | 176 | echo 'x+y' | perl -pe 's/\Qx+y/q($x+@y)/e' 177 | 178 | echo 'x+y' | perl -pe 's/\Qx+y/q($x\/@y)/e' 179 | 180 | echo 'x+y' | perl -pe 's|\Qx+y|q($x/@y)|e' 181 | 182 | echo 'x+y' | perl -pe 's|\Qx+y|q($x/@y\\\z)|e' 183 | 184 | -------------------------------------------------------------------------------- /code_snippets/Multiple_file_input.sh: -------------------------------------------------------------------------------- 1 | ## @ARGV, $ARGV and ARGV 2 | 3 | perl -E 'say join "\n", @ARGV' f[1-3].txt greeting.txt 4 | 5 | perl -nE 'say "$#ARGV: " . join ",", @ARGV' f[12].txt table.txt 6 | 7 | perl -ne 'print "--- $ARGV ---\n" if $. == 1; 8 | print; 9 | close ARGV if eof' greeting.txt table.txt 10 | 11 | perl -ne 'print if eof' greeting.txt table.txt 12 | 13 | perl -ne 'print and close ARGV if $.==2' greeting.txt table.txt 14 | 15 | perl -pe 'close ARGV if $.>=1' greeting.txt table.txt 16 | 17 | perl -e 'print scalar readline' greeting.txt 18 | 19 | perl -e '$line = <>; print "$line---\n"; print <>' greeting.txt 20 | 21 | perl -E 'say getc' ' 26 | 27 | printf 'apple\nmango\n' | perl -e 'print <>' greeting.txt 28 | 29 | printf 'apple\nmango\n' | perl -e 'print ' greeting.txt 30 | 31 | ## Skipping remaining contents per file 32 | 33 | perl -ne '/\bba/ ? close ARGV : print' ip.txt table.txt 34 | 35 | perl -nE 'if(/I/){say $ARGV; close ARGV}' f[1-3].txt greeting.txt 36 | 37 | perl -nE '$m1=1 if /e\b/; $m2=1 if /[bm]at/i; 38 | if($m1 && $m2){say $ARGV; $m1=$m2=0; close ARGV; next}; 39 | $m1=$m2=0 if eof' f[1-3].txt greeting.txt 40 | 41 | -------------------------------------------------------------------------------- /code_snippets/Oneliner_introduction.sh: -------------------------------------------------------------------------------- 1 | ## Executing Perl code 2 | 3 | echo 'print "Hello Perl\n"' > hello.pl 4 | 5 | perl hello.pl 6 | 7 | perl -e 'print "Hello Perl\n"' 8 | 9 | perl -le '$x=25; $y=12; print $x**$y' 10 | 11 | perl -E '$x=25; $y=12; say $x**$y' 12 | 13 | ## Filtering 14 | 15 | printf 'gate\napple\nwhat\nkite\n' 16 | 17 | printf 'gate\napple\nwhat\nkite\n' | perl -ne 'print if /at/' 18 | 19 | printf 'gate\napple\nwhat\nkite\n' | perl -ne 'print if !/e/' 20 | 21 | cat table.txt 22 | 23 | perl -nE 'say $& if /(? out.txt")' 74 | 75 | cat out.txt 76 | 77 | perl -E '$es=system("ls anchors.txt"); say $es' 78 | 79 | perl -E 'system("ls anchors.txt"); say $?' 80 | 81 | perl -E 'system("ls xyz.txt"); say $?' 82 | 83 | perl -e '$words = `wc -w $n; $f=0 if /6/' 73 | 74 | seq 30 | perl -ne 'BEGIN{$n=2; $c=0} if(/4/){$f=1; $c++} 75 | print if $f && $c!=$n; $f=0 if /6/' 76 | 77 | seq 30 | perl -ne 'if(/4/){$f=1; $buf=$_; next} 78 | $buf .= $_ if $f; 79 | if(/6/){$f=0; print $buf if $buf=~/^15$/m}' 80 | 81 | ## Broken blocks 82 | 83 | cat broken.txt 84 | 85 | perl -ne 'if(/error/){$f=1; $buf=$_; next} 86 | $buf .= $_ if $f; 87 | if(/state/){print $buf if $f; $f=0}' broken.txt 88 | 89 | -------------------------------------------------------------------------------- /code_snippets/Record_separators.sh: -------------------------------------------------------------------------------- 1 | ## Input record separator 2 | 3 | printf 'this,is\na,sample,text' | perl -nE 'BEGIN{$/ = ","} say "$.)$_"' 4 | 5 | printf 'this,is\na,sample,text' | perl -lne 'BEGIN{$/ = ","} print "$.)$_"' 6 | 7 | cat report.log 8 | 9 | perl -lne 'BEGIN{$/ = "Error:"} print if /something/' report.log 10 | 11 | ## Single character separator with the -0 option 12 | 13 | s='this:is:a:sample:string' 14 | 15 | echo "$s" | perl -0072 -lnE 'say "$.) $_"' 16 | 17 | echo "$s" | perl -0072 -lnE 'say $_ if /a/' 18 | 19 | s='this:is:a:sample:string' 20 | 21 | echo "$s" | perl -l -0072 -ne 'print if /a/' 22 | 23 | echo "$s" | perl -0072 -lne 'print if /a/' 24 | 25 | s=' a\t\tb:1000\n\n\t \n\n123 7777:x y \n \n z :apple banana cherry' 26 | 27 | printf '%b' "$s" | perl -0072 -lanE 'say join ",", @F' 28 | 29 | ## NUL separator 30 | 31 | printf 'apple\0banana\0' | cat -v 32 | 33 | printf 'apple\0banana\0' | perl -ln0e 'print' 34 | 35 | ## Slurping entire input 36 | 37 | cat paths.txt 38 | 39 | perl -0777 -pe 's|(? } 20 | print if exists $h{$_}' ' colors_1.txt colors_2.txt 25 | 26 | perl -MList::Compare -e '@a1=; @a2=<>; 27 | print List::Compare->new(\@a1, \@a2)->get_union 28 | ' ; @a2=<>; 31 | print List::Compare->new(\@a1, \@a2)->get_intersection 32 | ' ; @a2=<>; 35 | print List::Compare->new(\@a1, \@a2)->get_unique 36 | ' =$h{$F[0]} } 63 | ' dept_mark.txt marks.txt 64 | 65 | cat role.txt 66 | 67 | perl -lane 'if(!$#ARGV){ $r{$F[0]}=$F[1]; $.=0 } 68 | else{ print join "\t", @F, $.==1 ? "Role" : $r{$F[1]} } 69 | ' role.txt marks.txt 70 | 71 | ## Based on line numbers 72 | 73 | perl -pe 'BEGIN{ $m=3; $n=2; $s = for 1..$n } 74 | $_ = $s if $. == $m' )[-1] > 0' search.txt 81 | 82 | cat repl.txt 83 | 84 | perl -0777 -ne '$#ARGV==1 ? $s=$_ : $#ARGV==0 ? $r=$_ : 85 | print s/\Q$s/$r/gr' search.txt repl.txt table.txt 86 | 87 | ## Add file content conditionally 88 | 89 | perl -pe 'BEGIN{$r = join "", } $_=$r if /[ot]/' } 92 | print $r if /nice/' } 95 | $_ .= $r if /nice/' [1] 40 | while $row = Text::CSV_XS->new->getline(*ARGV)' 41 | 42 | cat newline.csv 43 | 44 | perl -MText::CSV_XS -E ' 45 | while($row = Text::CSV_XS->new({binary => 1})->getline(*ARGV)) 46 | {say "$row->[1]\n-----"}' newline.csv 47 | 48 | perl -MText::CSV_XS -E ' 49 | while($row = Text::CSV_XS->new({sep_char => "\t"})->getline(*ARGV)) 50 | {say join ",", @$row if $row->[0] eq "CSE"}' marks.txt 51 | 52 | ## JSON 53 | 54 | s='{"greeting":"hi","marks":[78,62,93]}' 55 | 56 | echo "$s" | perl -MCpanel::JSON::XS -E '$ip=decode_json <>; say $ip->{greeting}' 57 | 58 | echo "$s" | perl -MCpanel::JSON::XS -E '$ip=decode_json <>; 59 | say join ":", @{$ip->{marks}}' 60 | 61 | type pj 62 | 63 | pj() { perl -MCpanel::JSON::XS -0777 -E '$ip=decode_json <>;'"$@" ; } 64 | 65 | s='{"greeting":"hi","marks":[78,62,93]}' 66 | 67 | echo "$s" | pj 'say $ip->{greeting}' 68 | 69 | cat sample.json 70 | 71 | pj 'for (keys %$ip){say "$_:$ip->{$_}" if !/e/}' sample.json 72 | 73 | pj '$"=","; while(($k,$v) = each %{$ip->{language}}) 74 | {say "$k:@{$v}" if $k=~/t/}' sample.json 75 | 76 | s='{"greeting":"hi","marks":[78,62,93],"fruit":"apple"}' 77 | 78 | echo "$s" | cpanel_json_xs 79 | 80 | ## Convert one-liners to pretty formatted scripts 81 | 82 | perl -MO=Deparse -ne 'print if /at/' 83 | 84 | perl -MO=Deparse -pe 's/ /:/g' 85 | 86 | perl -MO=Deparse -l -0072 -ne 'print if /a/' 87 | 88 | perl -MO=Deparse -00 -ne 'print if /it/' 89 | 90 | perl -MO=Deparse -ne 'print if /4/ }{ print "==> the end\n"' 91 | 92 | perl -MO=Deparse -ne 'print if /4/' > script.pl 93 | 94 | cat script.pl 95 | 96 | perl script.pl table.txt 97 | 98 | -------------------------------------------------------------------------------- /example_files/anchors.txt: -------------------------------------------------------------------------------- 1 | sub par 2 | spar 3 | apparent effort 4 | two spare computers 5 | cart part tart mart 6 | -------------------------------------------------------------------------------- /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/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/colors_2.txt: -------------------------------------------------------------------------------- 1 | light blue 2 | black 3 | dark green 4 | yellow 5 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /example_files/dept.txt: -------------------------------------------------------------------------------- 1 | CSE 2 | ECE 3 | -------------------------------------------------------------------------------- /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/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/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/f1.txt: -------------------------------------------------------------------------------- 1 | I ate 3 apples 2 | -------------------------------------------------------------------------------- /example_files/f2.txt: -------------------------------------------------------------------------------- 1 | I bought two balls and 3 bats 2 | -------------------------------------------------------------------------------- /example_files/f3.txt: -------------------------------------------------------------------------------- 1 | Name Physics Maths 2 | Moe 76 82 3 | Raj 56 64 4 | -------------------------------------------------------------------------------- /example_files/fruits.txt: -------------------------------------------------------------------------------- 1 | banana 2 | papaya 3 | mango 4 | -------------------------------------------------------------------------------- /example_files/greeting.txt: -------------------------------------------------------------------------------- 1 | Hi there 2 | Have a nice day 3 | Good bye 4 | -------------------------------------------------------------------------------- /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/items.txt: -------------------------------------------------------------------------------- 1 | apple fig banana 2 | 50 10 200 3 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /example_files/newline.csv: -------------------------------------------------------------------------------- 1 | apple,"1 2 | 2 3 | 3",good 4 | guava,"32 5 | 54",nice 6 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /example_files/paths.txt: -------------------------------------------------------------------------------- 1 | /home/joe/report.log 2 | /home/ram/power.log 3 | /home/rambo/errors.log 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/repl.txt: -------------------------------------------------------------------------------- 1 | 2$1$&3 2 | wise ice go goa 3 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /example_files/role.txt: -------------------------------------------------------------------------------- 1 | Raj class_rep 2 | Amy sports_rep 3 | Tia placement_rep 4 | -------------------------------------------------------------------------------- /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/search.txt: -------------------------------------------------------------------------------- 1 | brown bread mat hair 42 2 | blue cake mug shirt -7 3 | -------------------------------------------------------------------------------- /example_files/t1.txt: -------------------------------------------------------------------------------- 1 | have a nice day 2 | bad morning 3 | what a pleasant evening 4 | -------------------------------------------------------------------------------- /example_files/t2.txt: -------------------------------------------------------------------------------- 1 | worse than ever 2 | too bad 3 | -------------------------------------------------------------------------------- /example_files/table.txt: -------------------------------------------------------------------------------- 1 | brown bread mat hair 42 2 | blue cake mug shirt -7 3 | yellow banana window shoes 3.14 4 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | $ perl -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 | $ perl -anE 'say $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 | $ perl -ane 'print if $#F < 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 | $ perl -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 | $ perl -pe 's/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 | $ perl -anE 'BEGIN{$p=1} $p *= $F[-1]; END{say $p}' table.txt 68 | -923.16 69 | ``` 70 | 71 | **7)** Append `.` to all the input lines for the given stdin data. 72 | 73 | ```bash 74 | # can also use: perl -lne 'print "$_."' 75 | $ printf 'last\nappend\nstop\ntail\n' | perl -pe 's/$/./' 76 | last. 77 | append. 78 | stop. 79 | tail. 80 | ``` 81 | 82 | **8)** Use the contents of the `s` variable to display all 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 | $ r="$s" perl -ne 'print if /\B$ENV{r}/' ip.txt 88 | This game is good 89 | ``` 90 | 91 | **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. 92 | 93 | ```bash 94 | $ s='report.log ip.txt sorted.txt' 95 | $ echo "$s" | perl -ane 'system("cat $F[1]")' 96 | Hello World 97 | How are you 98 | This game is good 99 | Today is sunny 100 | 12345 101 | You are funny 102 | 103 | $ s='power.txt table.txt' 104 | $ echo "$s" | perl -ane 'system("cat $F[1]")' 105 | brown bread mat hair 42 106 | blue cake mug shirt -7 107 | yellow banana window shoes 3.14 108 | ``` 109 | 110 |
111 | 112 | # Line processing 113 | 114 | **1)** For the given input, display except the third line. 115 | 116 | ```bash 117 | $ seq 34 37 | perl -ne 'print if $. != 3' 118 | 34 119 | 35 120 | 37 121 | ``` 122 | 123 | **2)** Display only the fourth, fifth, sixth and seventh lines for the given input. 124 | 125 | ```bash 126 | $ seq 65 78 | perl -ne 'print if 4..7' 127 | 68 128 | 69 129 | 70 130 | 71 131 | ``` 132 | 133 | **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. 134 | 135 | ```bash 136 | $ cat ip.txt 137 | Hello World 138 | How are you 139 | This game is good 140 | Today is sunny 141 | 12345 142 | You are funny 143 | 144 | $ perl -ne 'print if $. > 3 && s/are|is/$& not/g' ip.txt 145 | Today is not sunny 146 | You are not funny 147 | ``` 148 | 149 | **4)** For the given stdin, display only the first three lines. Avoid processing lines that are not relevant. 150 | 151 | ```bash 152 | $ seq 14 25 | perl -pe 'exit if $. > 3' 153 | 14 154 | 15 155 | 16 156 | ``` 157 | 158 | **5)** For the input file `ip.txt`, display all lines from the start of the file till the first occurrence of `game`. 159 | 160 | ```bash 161 | $ perl -ne 'print; exit if /game/' ip.txt 162 | Hello World 163 | How are you 164 | This game is good 165 | ``` 166 | 167 | **6)** For the input file `ip.txt`, display all lines that contain `is` but not `good`. 168 | 169 | ```bash 170 | $ perl -ne 'print if /is/ && !/good/' ip.txt 171 | Today is sunny 172 | ``` 173 | 174 | **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. 175 | 176 | ```bash 177 | # can also use: perl -ne 'print if s/.*?(\w+)\W+is\W+(\w+).*/$2:$1/' ip.txt 178 | $ perl -nE 'say "$2:$1" if /(\w+)\W+is\W+(\w+)/' ip.txt 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 | $ perl -pe 's/0xA0/0x50/g; s/0xFF/0x7F/g' hex.txt 192 | start: 0x50, func1: 0x50 193 | end: 0x7F, func2: 0xB0 194 | restart: 0x5010, func3: 0x7F 195 | ``` 196 | 197 | **9)** Find the starting index of the 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. 198 | 199 | ```bash 200 | $ cat idx.txt 201 | match after the last newline character 202 | and then you want to test 203 | this is good bye then 204 | you were there to see? 205 | 206 | $ perl -nE '/is|the|was|to/; say $-[0]' idx.txt 207 | 12 208 | 4 209 | 2 210 | 9 211 | ``` 212 | 213 | **10)** Display all lines containing `[4]*` for the given stdin data. 214 | 215 | ```bash 216 | # can also use: perl -ne 'print if /\Q[4]*/' 217 | $ printf '2.3/[4]*6\n2[4]5\n5.3-[4]*9\n' | perl -ne 'print if index($_, "[4]*") != -1' 218 | 2.3/[4]*6 219 | 5.3-[4]*9 220 | ``` 221 | 222 | **11)** For the given input string, replace all lowercase alphabets to `x` only for words starting with `m`. 223 | 224 | ```bash 225 | $ s='ma2T3a a2p kite e2e3m meet' 226 | $ echo "$s" | perl -pe 's/\bm\w+/$&=~tr|a-z|x|r/ge' 227 | xx2T3x a2p kite e2e3m xxxx 228 | ``` 229 | 230 | **12)** 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). 231 | 232 | ```bash 233 | # can also use: perl -pe 'tr/aeiou\n//cd if /you/ .. 4' ip.txt 234 | $ perl -lpe 'tr/aeiou//cd if /you/ .. 4' ip.txt 235 | Hello World 236 | oaeou 237 | iaeioo 238 | oaiu 239 | 12345 240 | You are funny 241 | ``` 242 | 243 | **13)** For the input file `sample.txt`, display from the start of the file till the first occurrence of `are`, excluding the matching line. 244 | 245 | ```bash 246 | $ cat sample.txt 247 | Hello World 248 | 249 | Good day 250 | How are you 251 | 252 | Just do-it 253 | Believe it 254 | 255 | Today is sunny 256 | Not a bit funny 257 | No doubt you like it too 258 | 259 | Much ado about nothing 260 | He he he 261 | 262 | $ perl -pe 'exit if /are/' sample.txt 263 | Hello World 264 | 265 | Good day 266 | ``` 267 | 268 | **14)** For the input file `sample.txt`, display from the last occurrence of `do` till the end of the file. 269 | 270 | ```bash 271 | $ tac sample.txt | perl -ne 'print; exit if /do/' | tac 272 | Much ado about nothing 273 | He he he 274 | ``` 275 | 276 | **15)** For the input file `sample.txt`, display from the 9th line till a line containing `you`. 277 | 278 | ```bash 279 | $ perl -ne 'print if 9 .. /you/' sample.txt 280 | Today is sunny 281 | Not a bit funny 282 | No doubt you like it too 283 | ``` 284 | 285 | **16)** Display only the odd numbered lines from `ip.txt`. 286 | 287 | ```bash 288 | $ perl -ne 'print if $.%2' ip.txt 289 | Hello World 290 | This game is good 291 | 12345 292 | ``` 293 | 294 | **17)** For the `table.txt` file, print only the line number for lines containing `air` or `win`. 295 | 296 | ```bash 297 | $ cat table.txt 298 | brown bread mat hair 42 299 | blue cake mug shirt -7 300 | yellow banana window shoes 3.14 301 | 302 | $ perl -nE 'say $. if /air|win/' table.txt 303 | 1 304 | 3 305 | ``` 306 | 307 | **18)** For the input file `table.txt`, calculate the sum of numbers in the last column, excluding the second line. 308 | 309 | ```bash 310 | $ perl -anE '$total += $F[-1] if $.!=2; END{say $total}' table.txt 311 | 45.14 312 | ``` 313 | 314 | **19)** Print the second and fourth line for every block of five lines. 315 | 316 | ```bash 317 | # can also use: seq 15 | perl -ne 'BEGIN{$h{2}=$h{4}=1} print if $h{$.%5}' 318 | $ seq 15 | perl -ne 'print if $.%5 == 2 || $.%5 == 4' 319 | 2 320 | 4 321 | 7 322 | 9 323 | 12 324 | 14 325 | ``` 326 | 327 | **20)** For the input file `ip.txt`, display all lines containing `e` or `u` but not both. 328 | 329 | ```bash 330 | $ perl -ne 'print if /e/ xor /u/' ip.txt 331 | Hello World 332 | This game is good 333 | Today is sunny 334 | ``` 335 | 336 |
337 | 338 | # In-place file editing 339 | 340 | **1)** 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` 341 | 342 | ```bash 343 | $ cat text.txt 344 | can ran want plant 345 | tin fin fit mine line 346 | 347 | $ perl -i.orig -pe 's/in/an/g' text.txt 348 | 349 | $ cat text.txt 350 | can ran want plant 351 | tan fan fit mane lane 352 | $ cat text.txt.orig 353 | can ran want plant 354 | tin fin fit mine line 355 | ``` 356 | 357 | **2)** 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. 358 | 359 | ```bash 360 | $ cat text.txt 361 | can ran want plant 362 | tan fan fit mane lane 363 | 364 | $ perl -i -pe 's/an/in/g' text.txt 365 | 366 | $ cat text.txt 367 | cin rin wint plint 368 | tin fin fit mine line 369 | $ diff text.txt text.txt.orig 370 | 1c1 371 | < cin rin wint plint 372 | --- 373 | > can ran want plant 374 | ``` 375 | 376 | **3)** For the input file `copyright.txt`, replace `copyright: 2018` with `copyright: 2020` and write back the changes to `copyright.txt` itself. The original contents should get saved to `2018_copyright.txt.bkp` 377 | 378 | ```bash 379 | $ cat copyright.txt 380 | bla bla 2015 bla 381 | blah 2018 blah 382 | bla bla bla 383 | copyright: 2018 384 | 385 | $ perl -i'2018_*.bkp' -pe 's/copyright: \K2018/2020/g' copyright.txt 386 | 387 | $ cat copyright.txt 388 | bla bla 2015 bla 389 | blah 2018 blah 390 | bla bla bla 391 | copyright: 2020 392 | $ cat 2018_copyright.txt.bkp 393 | bla bla 2015 bla 394 | blah 2018 blah 395 | bla bla bla 396 | copyright: 2018 397 | ``` 398 | 399 | **4)** In the code sample shown below, two files are created by redirecting the output of the `echo` command. Then a Perl command is used to edit `b1.txt` in-place as well as create a backup named `bkp.b1.txt`. Will the Perl command work as expected? If not, why? 400 | 401 | ```bash 402 | $ echo '2 apples' > b1.txt 403 | $ echo '5 bananas' > -ibkp.txt 404 | $ perl -ibkp.* -pe 's/2/two/' b1.txt 405 | ``` 406 | 407 | Unquoted strings on the command line are subjected to shell interpretation. So, `-ibkp.*` will get expanded as `-ibkp.txt` (as there exists a file whose name starts with `-ibkp.`). This results in back up filename as `b1.txtbkp.txt` (because `bkp.txt` will be treated as the suffix to be added to `b1.txt`). The correct usage is `perl -i'bkp.*' -pe 's/2/two/' b1.txt` to get `bkp.b1.txt` as the back up filename. 408 | 409 | **5)** For the input file `pets.txt`, remove the first occurrence of `I like ` from each line and write back the changes to `pets.txt` itself. The original contents should get saved with the same filename inside the `bkp` directory. Assume that you do not know whether `bkp` exists or not in the current working directory. 410 | 411 | ```bash 412 | $ cat pets.txt 413 | I like cats 414 | I like parrots 415 | I like dogs 416 | 417 | $ mkdir -p bkp 418 | $ perl -i'bkp/*' -pe 's/I like //' pets.txt 419 | 420 | $ cat pets.txt 421 | cats 422 | parrots 423 | dogs 424 | $ cat bkp/pets.txt 425 | I like cats 426 | I like parrots 427 | I like dogs 428 | ``` 429 | 430 |
431 | 432 | # Field separators 433 | 434 | **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. 435 | 436 | ```bash 437 | $ cat brackets.txt 438 | foo blah blah(ice) 123 xyz$ 439 | (almond-pista) choco 440 | yo )yoyo( yo 441 | 442 | # can also use: perl -nE 'say /[()]([^()]+)[()]/' brackets.txt 443 | $ perl -F'[()]' -nE 'say $F[1]' brackets.txt 444 | ice 445 | almond-pista 446 | yoyo 447 | ``` 448 | 449 | **2)** For the input file `scores.csv`, extract `Name` and `Physics` fields in the format shown below. 450 | 451 | ```bash 452 | $ cat scores.csv 453 | Name,Maths,Physics,Chemistry 454 | Blue,67,46,99 455 | Lin,78,83,80 456 | Er,56,79,92 457 | Cy,97,98,95 458 | Ort,68,72,66 459 | Ith,100,100,100 460 | 461 | # can also use: perl -F, -lane 'print join ":", @F[0,2]' scores.csv 462 | $ perl -F, -lane 'print "$F[0]:$F[2]"' scores.csv 463 | Name:Physics 464 | Blue:46 465 | Lin:83 466 | Er:79 467 | Cy:98 468 | Ort:72 469 | Ith:100 470 | ``` 471 | 472 | **3)** For the input file `scores.csv`, display names of those who've scored above `80` in Maths. 473 | 474 | ```bash 475 | $ perl -F, -lane 'print $F[0] if $F[1]>80' scores.csv 476 | Cy 477 | Ith 478 | ``` 479 | 480 | **4)** Display the number of word characters for the given inputs. Word definition here is same as used in regular expressions. Can you construct two different solutions as indicated below? 481 | 482 | ```bash 483 | # solve using the 's' operator 484 | $ echo 'hi there' | perl -nE 'say s/\w//g' 485 | 7 486 | 487 | # solve without using the substitution or transliteration operators 488 | $ echo 'u-no;co%."(do_12:as' | perl -F'\w' -anE 'say $#F' 489 | 12 490 | ``` 491 | 492 | **Note** that the first solution will print an empty string for lines not containing any word character, while the second one will print `0`. You can use `s/\w//g + 0` cover such corner cases. 493 | 494 | **5)** For the input file `quoted.txt`, extract the sequence of characters surrounded by double quotes and display them in the format shown below. 495 | 496 | ```bash 497 | $ cat quoted.txt 498 | 1 "grape" and "mango" and "guava" 499 | ("c 1""d""a-2""b") 500 | 501 | $ perl -nE 'say join ",", sort /"[^"]+"/g' quoted.txt 502 | "grape","guava","mango" 503 | "a-2","b","c 1","d" 504 | ``` 505 | 506 | **6)** Display only the third and fifth characters from each input line as shown below. 507 | 508 | ```bash 509 | $ printf 'restore\ncat one\ncricket' | perl -F -anE 'say @F[2,4]' 510 | so 511 | to 512 | ik 513 | ``` 514 | 515 | **7)** Transform the given input file `fw.txt` to get the output as shown below. If a field is empty (i.e. contains only space characters), replace it with `NA`. 516 | 517 | ```bash 518 | $ cat fw.txt 519 | 1.3 rs 90 0.134563 520 | 3.8 6 521 | 5.2 ye 8.2387 522 | 4.2 kt 32 45.1 523 | 524 | $ perl -ne '@f = unpack "a3x2a2x7a*"; 525 | $f[1] = "NA" if $f[1] eq " "; 526 | print join ",", @f' fw.txt 527 | 1.3,rs,0.134563 528 | 3.8,NA,6 529 | 5.2,ye,8.2387 530 | 4.2,kt,45.1 531 | ``` 532 | 533 | **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. 534 | 535 | ```bash 536 | $ perl -F, -ane 'print if $F[0]=~/[bt]/i || $.==1' scores.csv 537 | Name,Maths,Physics,Chemistry 538 | Blue,67,46,99 539 | Ort,68,72,66 540 | Ith,100,100,100 541 | ``` 542 | 543 | **9)** Extract all whole words containing `42` but not at the edge of a word. Assume a word cannot contain `42` more than once. 544 | 545 | ```bash 546 | $ s='hi42bye nice1423 bad42 cool_42a 42fake' 547 | $ echo "$s" | perl -nE 'say join "\n", /\w+42\w+/g' 548 | hi42bye 549 | nice1423 550 | cool_42a 551 | ``` 552 | 553 | **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. 554 | 555 | ```bash 556 | $ perl -F, -lane 'print join ",", @F, $.==1 ? "GP" : 557 | $F[1]/2 + ($F[2]+$F[3])/4' scores.csv 558 | Name,Maths,Physics,Chemistry,GP 559 | Blue,67,46,99,69.75 560 | Lin,78,83,80,79.75 561 | Er,56,79,92,70.75 562 | Cy,97,98,95,96.75 563 | Ort,68,72,66,68.5 564 | Ith,100,100,100,100 565 | ``` 566 | 567 | **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. 568 | 569 | ```bash 570 | $ cat mixed_fs.txt 571 | rose lily jasmine tulip 572 | pink blue white yellow 573 | car,mat,ball,basket 574 | light green,brown,black,purple 575 | apple,banana,cherry 576 | 577 | $ perl -lne '$s = $.<3 ? " " : ","; 578 | print join $s, (split $s)[0,1]' mixed_fs.txt 579 | rose lily 580 | pink blue 581 | car,mat 582 | light green,brown 583 | apple,banana 584 | ``` 585 | 586 | **12)** For the given space separated numbers, filter only numbers in the range `20` to `1000` (inclusive). 587 | 588 | ```bash 589 | $ s='20 -983 5 756 634223 1000' 590 | 591 | $ echo "$s" | perl -lane 'print join " ", grep {$_>=20 && $_<=1000} @F' 592 | 20 756 1000 593 | ``` 594 | 595 | **13)** For the given input file `words.txt`, filter all lines containing characters in ascending and descending order. 596 | 597 | ```bash 598 | $ cat words.txt 599 | bot 600 | art 601 | are 602 | boat 603 | toe 604 | flee 605 | reed 606 | 607 | # ascending order 608 | $ perl -F -lane 'print if $_ eq join "", sort @F' words.txt 609 | bot 610 | art 611 | 612 | # descending order 613 | $ perl -F -lane 'print if $_ eq join "", reverse sort @F' words.txt 614 | toe 615 | reed 616 | ``` 617 | 618 | **14)** For the given space separated words, extract the three longest words. 619 | 620 | ```bash 621 | $ s='I bought two bananas and three mangoes' 622 | 623 | $ echo "$s" | perl -anE 'say join "\n", (sort {length($b) <=> length($a)} @F)[0..2]' 624 | bananas 625 | mangoes 626 | bought 627 | ``` 628 | 629 | **15)** Convert the contents of `split.txt` as shown below. 630 | 631 | ```bash 632 | $ cat split.txt 633 | apple,1:2:5,mango 634 | wry,4,look 635 | pencil,3:8,paper 636 | 637 | $ perl -F, -lane 'print join ",", $F[0],$_,$F[2] for split /:/,$F[1]' split.txt 638 | apple,1,mango 639 | apple,2,mango 640 | apple,5,mango 641 | wry,4,look 642 | pencil,3,paper 643 | pencil,8,paper 644 | ``` 645 | 646 | **16)** Generate string combinations as shown below for the given input string passed as an environment variable. 647 | 648 | ```bash 649 | $ s='{x,y,z}{1,2,3}' perl -E 'say join " ", glob $ENV{s}' 650 | x1 x2 x3 y1 y2 y3 z1 z2 z3 651 | ``` 652 | 653 | **17)** For the input file `varying_fields.txt`, construct a solution to get the output shown below. 654 | 655 | ```bash 656 | $ cat varying_fields.txt 657 | hi,bye,there,was,here,to 658 | 1,2,3,4,5 659 | 660 | $ perl -F, -lane 'print join ":", @F[0,1,-1]' varying_fields.txt 661 | hi:bye:to 662 | 1:2:5 663 | ``` 664 | 665 | **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 `s` operator. 666 | 667 | ```bash 668 | $ cat fields.txt 669 | 42:cat 670 | twelve:a2b 671 | we:be:he:0:a:b:bother 672 | apple:banana-42:cherry: 673 | dragon:unicorn:centaur 674 | 675 | $ perl -F'/:/,$_,-1' -lane '$#F-- if /\d.*:/; print join ":", @F' fields.txt 676 | 42 677 | twelve:a2b 678 | we:be:he:0:a:b 679 | apple:banana-42:cherry 680 | dragon:unicorn:centaur 681 | ``` 682 | 683 | **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. 684 | 685 | ```bash 686 | $ s='applecatfigCaT12345cAtbanana' 687 | # can also use: perl -F'(?i)cat' -lane 'print join " ", @F, "42"' 688 | $ echo "$s" | perl -F'(?i)cat' -lane 'print "@F 42"' 689 | apple fig 12345 banana 42 690 | ``` 691 | 692 | **20)** For the input file `sample.txt`, filter lines containing 5 or more lowercase vowels. 693 | 694 | ```bash 695 | # can also use: perl -ne 'print if /([aeiou][^aeiou]*+){5}/' sample.txt 696 | $ perl -F'[aeiou]' -ane 'print if $#F>=5' sample.txt 697 | How are you 698 | Believe it 699 | No doubt you like it too 700 | Much ado about nothing 701 | ``` 702 | 703 |
704 | 705 | # Record separators 706 | 707 | **1)** The input file `jumbled.txt` consists of words separated by various delimiters. Display all words that contain `an` or `at` or `in` or `it`, one per line. 708 | 709 | ```bash 710 | $ cat jumbled.txt 711 | overcoats;furrowing-typeface%pewter##hobby 712 | wavering:concession/woof\retailer 713 | joint[]seer{intuition}titanic 714 | 715 | $ perl -0777 -nE 'say join "\n", /\w*[ai][nt]\w*/g' jumbled.txt 716 | overcoats 717 | furrowing 718 | wavering 719 | joint 720 | intuition 721 | titanic 722 | ``` 723 | 724 | **2)** Emulate `paste -sd,` with Perl. 725 | 726 | ```bash 727 | # this command joins all input lines with the ',' character 728 | $ paste -sd, ip.txt 729 | Hello World,How are you,This game is good,Today is sunny,12345,You are funny 730 | # make sure there's no ',' at the end of the line 731 | # and that there's a newline character at the end of the line 732 | $ perl -lpe '$\ = eof ? "\n" : ","' ip.txt 733 | Hello World,How are you,This game is good,Today is sunny,12345,You are funny 734 | 735 | # if there's only one line in input, again make sure there's no trailing ',' 736 | # and that there's a newline character at the end of the line 737 | $ printf 'fig' | paste -sd, 738 | fig 739 | $ printf 'fig' | perl -lpe '$\ = eof ? "\n" : ","' 740 | fig 741 | ``` 742 | 743 | **3)** For the input file `sample.txt`, extract all paragraphs having words starting with `do`. 744 | 745 | ```bash 746 | $ cat sample.txt 747 | Hello World 748 | 749 | Good day 750 | How are you 751 | 752 | Just do-it 753 | Believe it 754 | 755 | Today is sunny 756 | Not a bit funny 757 | No doubt you like it too 758 | 759 | Much ado about nothing 760 | He he he 761 | 762 | # note that there's no extra empty line at the end of the output 763 | $ perl -00 -lnE 'if(/\bdo/){say $s, $_; $s="\n"}' sample.txt 764 | Just do-it 765 | Believe it 766 | 767 | Today is sunny 768 | Not a bit funny 769 | No doubt you like it too 770 | ``` 771 | 772 | **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. 773 | 774 | ```bash 775 | # note that there's no extra empty line at the end of the output 776 | $ perl -F'\n' -00 -lane '$\ = eof ? ".\n" : ".\n\n"; print join ". ", @F' sample.txt 777 | Hello World. 778 | 779 | Good day. How are you. 780 | 781 | Just do-it. Believe it. 782 | 783 | Today is sunny. Not a bit funny. No doubt you like it too. 784 | 785 | Much ado about nothing. He he he. 786 | ``` 787 | 788 | **5)** For the given input, use `;;` as the record separators and `:` as the field separators. Filter records whose second field is greater than `50`. 789 | 790 | ```bash 791 | $ s='mango:100;;apple:25;;grapes:75' 792 | 793 | # note that the output has ;; at the end, not a newline character 794 | $ printf "$s" | perl -F: -lane 'BEGIN{$/=$\=";;"} print if $F[1]>50' 795 | mango:100;;grapes:75;; 796 | ``` 797 | 798 | **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 the empty lines at the start and end of the file. 799 | 800 | ```bash 801 | $ perl -l -00 -ne 'print $s, $_; $s="\n\n"' f1.txt 802 | hello 803 | 804 | 805 | world 806 | 807 | 808 | apple 809 | banana 810 | cherry 811 | 812 | 813 | tea coffee 814 | chocolate 815 | ``` 816 | 817 | **7)** The sample string shown below uses `cat` as the record separator. Display only the even numbered records separated by a single empty line. 818 | 819 | ```bash 820 | $ s='applecatfigcat12345catbananacatguava:cat:mangocat3' 821 | $ echo "$s" | perl -lne 'BEGIN{$/ = "cat"} if($.%2==0){print $s, $_; $s="\n"}' 822 | fig 823 | 824 | banana 825 | 826 | :mango 827 | ``` 828 | 829 |
830 | 831 | # Using modules 832 | 833 | **1)** For the given space separated words, display the max word determined by alphabetic order. 834 | 835 | ```bash 836 | $ s='let in bat xml me lion' 837 | 838 | $ echo "$s" | perl -lane 'print ((sort @F)[-1])' 839 | xml 840 | ``` 841 | 842 | **2)** For the given space separated words, randomize the order of characters for each word. 843 | 844 | ```bash 845 | $ s='this is a sample sentence' 846 | 847 | # sample randomized output shown here, could be different for you 848 | $ echo "$s" | perl -MList::Util=shuffle -lane ' 849 | print join " ", map {join "", shuffle split//} @F' 850 | htis si a melasp ecnnsete 851 | ``` 852 | 853 | **3)** Use the [metacpan: XML::LibXML](https://metacpan.org/pod/XML::LibXML) module to get the content of all tags named `blue` for the input file `sample.xml`. See [grantm: Perl XML::LibXML by example](https://grantm.github.io/perl-libxml-by-example/) for a detailed book on the `XML::LibXML` module. 854 | 855 | ```bash 856 | $ cat sample.xml 857 | 858 | Hi there. How are you? 859 | I am good. 860 | 861 | flower 862 | sand stone 863 | sky 864 | water 865 | 866 | 867 | 868 | $ perl -MXML::LibXML -E '$ip = XML::LibXML->load_xml(location => $ARGV[0]); 869 | say $_->to_literal() for $ip->findnodes("//blue")' sample.xml 870 | flower 871 | sand stone 872 | ``` 873 | 874 | **4)** Display the current time in the format shown below. 875 | 876 | ```bash 877 | # output will be different for you 878 | # you can use %F to get YYYY-MM-DD format 879 | $ perl -MTime::Piece -E 'say localtime->strftime("%e-%b-%Y %T")' 880 | 12-Sep-2023 11:01:14 881 | ``` 882 | 883 | >![info](../images/info.svg) See [metacpan: DateTime](https://metacpan.org/pod/DateTime) for more comprehensive functions. 884 | 885 |
886 | 887 | # Multiple file input 888 | 889 | **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. 890 | 891 | ```bash 892 | # assume table.txt ip.txt are passed as file inputs 893 | $ perl -lane 'print ">$ARGV<" if $.==1; print "$F[-1]"; 894 | if($.==2){print "----------"; close ARGV} 895 | ' table.txt ip.txt 896 | >table.txt< 897 | 42 898 | -7 899 | ---------- 900 | >ip.txt< 901 | World 902 | you 903 | ---------- 904 | ``` 905 | 906 | **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. 907 | 908 | ```bash 909 | $ perl -anE 'if($F[2]=~/at|fun/){say $ARGV; close ARGV} 910 | ' sample.txt secrets.txt ip.txt table.txt 911 | secrets.txt 912 | ip.txt 913 | table.txt 914 | ``` 915 | 916 | **3)** Print the first 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. 917 | 918 | ```bash 919 | $ perl -pe 'print $s if $.==1; if($.==2){close ARGV; $s="---\n"} 920 | ' ip.txt sample.txt table.txt 921 | Hello World 922 | How are you 923 | --- 924 | Hello World 925 | 926 | --- 927 | brown bread mat hair 42 928 | blue cake mug shirt -7 929 | ``` 930 | 931 | **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. 932 | 933 | ```bash 934 | $ perl -lane 'print $F[1] if $.==3; close ARGV if eof' ip.txt sample.txt copyright.txt 935 | game 936 | day 937 | bla 938 | ``` 939 | 940 |
941 | 942 | # Processing multiple records 943 | 944 | **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`. 945 | 946 | ```bash 947 | $ perl -ne 'print if /do/ && $p1 eq "\n" && $p2=~/you/; $p2=$p1; $p1=$_' sample.txt 948 | Just do-it 949 | Much ado about nothing 950 | ``` 951 | 952 | **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). 953 | 954 | ```bash 955 | # for reference, here are all the matches 956 | $ grep -i 'do' sample.txt 957 | Just do-it 958 | No doubt you like it too 959 | Much ado about nothing 960 | $ grep -i 'not' sample.txt 961 | Not a bit funny 962 | Much ado about nothing 963 | 964 | $ perl -ne 'print if /do/i && ++$do==2; 965 | print if /not/i && ++$not==2;' sample.txt 966 | No doubt you like it too 967 | Much ado about nothing 968 | ``` 969 | 970 | **3)** For the input file `sample.txt`, print the matching line as well as `n` lines around the matching lines. The value for `n` is passed to the Perl command as an environment value. 971 | 972 | ```bash 973 | # match a line containing 'are' or 'bit' 974 | $ n=1 perl -e '@ip=<>; for(0..$#ip){$i=$_-$ENV{n}; $i=0 if $i<0; 975 | print @ip[$i..$_+$ENV{n}] if $ip[$_]=~/are|bit/}' sample.txt 976 | Good day 977 | How are you 978 | 979 | Today is sunny 980 | Not a bit funny 981 | No doubt you like it too 982 | 983 | # match a line containing 'World' 984 | $ n=2 perl -e '@ip=<>; for (0..$#ip){$i=$_-$ENV{n}; $i=0 if $i<0; 985 | print @ip[$i..$_+$ENV{n}] if $ip[$_]=~/World/}' sample.txt 986 | Hello World 987 | 988 | Good day 989 | ``` 990 | 991 | **4)** For the input file `broken.txt`, print all lines between the markers `top` and `bottom`. The first Perl 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. 992 | 993 | ```bash 994 | $ cat broken.txt 995 | top 996 | 3.14 997 | bottom 998 | --- 999 | top 1000 | 1234567890 1001 | bottom 1002 | top 1003 | Hi there 1004 | Have a nice day 1005 | Good bye 1006 | 1007 | # wrong output 1008 | $ perl -ne '$f=0 if /bottom/; print if $f; $f=1 if /top/' broken.txt 1009 | 3.14 1010 | 1234567890 1011 | Hi there 1012 | Have a nice day 1013 | Good bye 1014 | 1015 | # expected output 1016 | $ tac broken.txt | perl -ne '$f=0 if /top/; print if $f; $f=1 if /bottom/' | tac 1017 | 3.14 1018 | 1234567890 1019 | ``` 1020 | 1021 | **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. 1022 | 1023 | ```bash 1024 | $ cat concat.txt 1025 | %%% addr.txt 1026 | How are you 1027 | This game is good 1028 | Today %%% is sunny 1029 | %%% broken.txt 1030 | top %%% 1031 | 1234567890 1032 | bottom 1033 | %%% sample.txt 1034 | Just %%% do-it 1035 | Believe it 1036 | %%% mixed_fs.txt 1037 | pink blue white yellow 1038 | car,mat,ball,basket 1039 | 1040 | $ n=2 perl -ne '$c++ if /^%%% /; print if $c==$ENV{n}' concat.txt 1041 | %%% broken.txt 1042 | top %%% 1043 | 1234567890 1044 | bottom 1045 | 1046 | $ n=4 perl -ne '$c++ if /^%%% /; print if $c==$ENV{n}' concat.txt 1047 | %%% mixed_fs.txt 1048 | pink blue white yellow 1049 | car,mat,ball,basket 1050 | ``` 1051 | 1052 | **6)** For the input file `perl.md`, replace all occurrences of `perl` (irrespective of case) with `Perl`. But, do not replace any matches between ` ```perl ` and ` ``` ` lines (`perl` in these markers shouldn't be replaced either). Save the output in `out.md`. 1053 | 1054 | ```bash 1055 | $ perl -pe '$f=1 if /^```perl$/; s/perl/Perl/gi if !$f; 1056 | $f=0 if /^```$/' perl.md > out.md 1057 | 1058 | $ diff -sq out.md expected.md 1059 | Files out.md and expected.md are identical 1060 | ``` 1061 | 1062 | **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. 1063 | 1064 | ```bash 1065 | $ perl -ne 'if(eof){print $s,$p,$_; $s="---\n"}; $p=$_' ip.txt sample.txt table.txt 1066 | 12345 1067 | You are funny 1068 | --- 1069 | Much ado about nothing 1070 | He he he 1071 | --- 1072 | blue cake mug shirt -7 1073 | yellow banana window shoes 3.14 1074 | ``` 1075 | 1076 | **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. 1077 | 1078 | ```bash 1079 | $ cat lines.txt 1080 | Go There 1081 | come on 1082 | go there 1083 | --- 1084 | 2 apples and 5 mangoes 1085 | come on! 1086 | --- 1087 | 2 Apples 1088 | COME ON 1089 | 1090 | $ perl -ne 'print if $p ne "---\n"; $p=$_' lines.txt 1091 | Go There 1092 | come on 1093 | go there 1094 | --- 1095 | come on! 1096 | --- 1097 | COME ON 1098 | ``` 1099 | 1100 | **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. 1101 | 1102 | ```bash 1103 | $ cat result.csv 1104 | Amy,maths,89 1105 | Amy,physics,75 1106 | Joe,maths,79 1107 | John,chemistry,77 1108 | John,physics,91 1109 | Moe,maths,81 1110 | Ravi,physics,84 1111 | Ravi,chemistry,70 1112 | Yui,maths,92 1113 | 1114 | $ perl -F, -lape 'print "---" if $.>1 && $p ne $F[0]; $p=$F[0]' result.csv 1115 | Amy,maths,89 1116 | Amy,physics,75 1117 | --- 1118 | Joe,maths,79 1119 | --- 1120 | John,chemistry,77 1121 | John,physics,91 1122 | --- 1123 | Moe,maths,81 1124 | --- 1125 | Ravi,physics,84 1126 | Ravi,chemistry,70 1127 | --- 1128 | Yui,maths,92 1129 | ``` 1130 | 1131 |
1132 | 1133 | # Two file processing 1134 | 1135 | **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`. 1136 | 1137 | ```bash 1138 | $ cat match_words.txt 1139 | %whole(Hello)--{doubt}==ado== 1140 | just,\joint*,concession<=nice 1141 | 1142 | # 'concession' is one of the third words from 'match_words.txt' 1143 | # and second word from 'jumbled.txt' 1144 | $ perl -ne '@w=/\w++/g; $#ARGV==1 ? $h{$w[2]}=1 : 1145 | exists $h{$w[1]} && print 1146 | ' match_words.txt jumbled.txt sample.txt 1147 | wavering:concession/woof\retailer 1148 | No doubt you like it too 1149 | ``` 1150 | 1151 | **2)** Interleave the contents of `secrets.txt` with the contents of a file passed as stdin in the format as shown below. 1152 | 1153 | ```bash 1154 | $ perl -ne 'print $s, $_, scalar ; $s="---\n"' secrets.txt if $.==3' ip.txt 1199 | Hello World 1200 | How are you 1201 | Start working on that 1202 | project you always wanted 1203 | to, do not let it end 1204 | You are funny 1205 | ``` 1206 | 1207 | **5)** Insert one line from `jumbled.txt` before every two lines of `copyright.txt`. 1208 | 1209 | ```bash 1210 | $ perl -pe 'print scalar if $. % 2' 80 }' criteria.txt result.csv 1287 | Amy,maths,89 1288 | John,physics,91 1289 | Yui,maths,92 1290 | ``` 1291 | 1292 | **9)** Insert the contents of `hex.txt` before a line matching `cake` of the input file `table.txt` 1293 | 1294 | ```bash 1295 | $ perl -pe 'BEGIN{$r = join "", } print $r if /cake/' } $_=$r if /are/' 1321 | 1322 | # Dealing with duplicates 1323 | 1324 | **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. 1325 | 1326 | ```bash 1327 | $ cat lines.txt 1328 | Go There 1329 | come on 1330 | go there 1331 | --- 1332 | 2 apples and 5 mangoes 1333 | come on! 1334 | --- 1335 | 2 Apples 1336 | COME ON 1337 | 1338 | $ perl -ne 'print if !$h{lc $_}++' lines.txt 1339 | Go There 1340 | come on 1341 | --- 1342 | 2 apples and 5 mangoes 1343 | come on! 1344 | 2 Apples 1345 | ``` 1346 | 1347 | **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. 1348 | 1349 | ```bash 1350 | $ cat twos.txt 1351 | hehe haha 1352 | door floor 1353 | haha hehe 1354 | 6;8 3-4 1355 | true blue 1356 | hehe bebe 1357 | floor door 1358 | 3-4 6;8 1359 | tru eblue 1360 | haha hehe 1361 | 1362 | # can also use: perl -ane 'print if !$h{join " ", sort @F}++' twos.txt 1363 | $ perl -lane 'print if !$h{$F[0] le $F[1] ? $_ : "$F[1] $F[0]"}++' twos.txt 1364 | hehe haha 1365 | door floor 1366 | 6;8 3-4 1367 | true blue 1368 | hehe bebe 1369 | tru eblue 1370 | ``` 1371 | 1372 | **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. 1373 | 1374 | ```bash 1375 | $ perl -ane '$k = join " ", sort @F; 1376 | !$#ARGV ? !$h{$k}++ : $h{$k}==1 && print' twos.txt twos.txt 1377 | true blue 1378 | hehe bebe 1379 | tru eblue 1380 | ``` 1381 | 1382 |
1383 | 1384 | # Perl rename command 1385 | 1386 | **1)** Determine and implement the rename logic based on the filenames and expected output shown below. 1387 | 1388 | ```bash 1389 | $ touch ' (2020) Report part 1 . txt ' 'analysis Part 3 (2018) .log' 1390 | 1391 | $ rename 's/^\h+|\h+$|[()]//g; s/\h*\.\h*/./g; s/\s+/_/g; s/.+/\L$&/' * 1392 | 1393 | $ ls 1394 | 2020_report_part_1.txt analysis_part_3_2018.log 1395 | ``` 1396 | 1397 | **2)** See [unix.stackexchange: rename Q&A sorted by votes](https://unix.stackexchange.com/questions/tagged/rename?tab=Votes) for further reading as well as a source for exercises. 1398 | 1399 | -------------------------------------------------------------------------------- /exercises/Exercises.md: -------------------------------------------------------------------------------- 1 | # Exercises 2 | 3 | >![info](../images/info.svg) For solutions, see [Exercise_solutions.md](https://github.com/learnbyexample/learn_perl_oneliners/blob/main/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.16 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 the contents of the `s` variable to display all 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)** Find the starting index of the 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. 198 | 199 | ```bash 200 | $ cat idx.txt 201 | match after the last newline character 202 | and then you want to test 203 | this is good bye then 204 | you were there to see? 205 | 206 | ##### add your solution here 207 | 12 208 | 4 209 | 2 210 | 9 211 | ``` 212 | 213 | **10)** Display all lines containing `[4]*` for the given stdin data. 214 | 215 | ```bash 216 | $ printf '2.3/[4]*6\n2[4]5\n5.3-[4]*9\n' | ##### add your solution here 217 | 2.3/[4]*6 218 | 5.3-[4]*9 219 | ``` 220 | 221 | **11)** For the given input string, replace all lowercase alphabets to `x` only for words starting with `m`. 222 | 223 | ```bash 224 | $ s='ma2T3a a2p kite e2e3m meet' 225 | $ echo "$s" | ##### add your solution here 226 | xx2T3x a2p kite e2e3m xxxx 227 | ``` 228 | 229 | **12)** 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). 230 | 231 | ```bash 232 | ##### add your solution here 233 | Hello World 234 | oaeou 235 | iaeioo 236 | oaiu 237 | 12345 238 | You are funny 239 | ``` 240 | 241 | **13)** For the input file `sample.txt`, display from the start of the file till the first occurrence of `are`, excluding the matching line. 242 | 243 | ```bash 244 | $ cat sample.txt 245 | Hello World 246 | 247 | Good day 248 | How are you 249 | 250 | Just do-it 251 | Believe it 252 | 253 | Today is sunny 254 | Not a bit funny 255 | No doubt you like it too 256 | 257 | Much ado about nothing 258 | He he he 259 | 260 | ##### add your solution here 261 | Hello World 262 | 263 | Good day 264 | ``` 265 | 266 | **14)** For the input file `sample.txt`, display from the last occurrence of `do` till the end of the file. 267 | 268 | ```bash 269 | ##### add your solution here 270 | Much ado about nothing 271 | He he he 272 | ``` 273 | 274 | **15)** For the input file `sample.txt`, display from the 9th line till a line containing `you`. 275 | 276 | ```bash 277 | ##### add your solution here 278 | Today is sunny 279 | Not a bit funny 280 | No doubt you like it too 281 | ``` 282 | 283 | **16)** Display only the odd numbered lines from `ip.txt`. 284 | 285 | ```bash 286 | ##### add your solution here 287 | Hello World 288 | This game is good 289 | 12345 290 | ``` 291 | 292 | **17)** For the `table.txt` file, print only the line number for lines containing `air` or `win`. 293 | 294 | ```bash 295 | $ cat table.txt 296 | brown bread mat hair 42 297 | blue cake mug shirt -7 298 | yellow banana window shoes 3.14 299 | 300 | ##### add your solution here 301 | 1 302 | 3 303 | ``` 304 | 305 | **18)** For the input file `table.txt`, calculate the sum of numbers in the last column, excluding the second line. 306 | 307 | ```bash 308 | ##### add your solution here 309 | 45.14 310 | ``` 311 | 312 | **19)** Print the second and fourth line for every block of five lines. 313 | 314 | ```bash 315 | $ seq 15 | ##### add your solution here 316 | 2 317 | 4 318 | 7 319 | 9 320 | 12 321 | 14 322 | ``` 323 | 324 | **20)** For the input file `ip.txt`, display all lines containing `e` or `u` but not both. 325 | 326 | ```bash 327 | ##### add your solution here 328 | Hello World 329 | This game is good 330 | Today is sunny 331 | ``` 332 | 333 |
334 | 335 | # In-place file editing 336 | 337 | **1)** 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` 338 | 339 | ```bash 340 | $ cat text.txt 341 | can ran want plant 342 | tin fin fit mine line 343 | 344 | ##### add your solution here 345 | 346 | $ cat text.txt 347 | can ran want plant 348 | tan fan fit mane lane 349 | $ cat text.txt.orig 350 | can ran want plant 351 | tin fin fit mine line 352 | ``` 353 | 354 | **2)** 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. 355 | 356 | ```bash 357 | $ cat text.txt 358 | can ran want plant 359 | tan fan fit mane lane 360 | 361 | ##### add your solution here 362 | 363 | $ cat text.txt 364 | cin rin wint plint 365 | tin fin fit mine line 366 | $ diff text.txt text.txt.orig 367 | 1c1 368 | < cin rin wint plint 369 | --- 370 | > can ran want plant 371 | ``` 372 | 373 | **3)** For the input file `copyright.txt`, replace `copyright: 2018` with `copyright: 2020` and write back the changes to `copyright.txt` itself. The original contents should get saved to `2018_copyright.txt.bkp` 374 | 375 | ```bash 376 | $ cat copyright.txt 377 | bla bla 2015 bla 378 | blah 2018 blah 379 | bla bla bla 380 | copyright: 2018 381 | 382 | ##### add your solution here 383 | 384 | $ cat copyright.txt 385 | bla bla 2015 bla 386 | blah 2018 blah 387 | bla bla bla 388 | copyright: 2020 389 | $ cat 2018_copyright.txt.bkp 390 | bla bla 2015 bla 391 | blah 2018 blah 392 | bla bla bla 393 | copyright: 2018 394 | ``` 395 | 396 | **4)** In the code sample shown below, two files are created by redirecting the output of the `echo` command. Then a Perl command is used to edit `b1.txt` in-place as well as create a backup named `bkp.b1.txt`. Will the Perl command work as expected? If not, why? 397 | 398 | ```bash 399 | $ echo '2 apples' > b1.txt 400 | $ echo '5 bananas' > -ibkp.txt 401 | $ perl -ibkp.* -pe 's/2/two/' b1.txt 402 | ``` 403 | 404 | **5)** For the input file `pets.txt`, remove the first occurrence of `I like ` from each line and write back the changes to `pets.txt` itself. The original contents should get saved with the same filename inside the `bkp` directory. Assume that you do not know whether `bkp` exists or not in the current working directory. 405 | 406 | ```bash 407 | $ cat pets.txt 408 | I like cats 409 | I like parrots 410 | I like dogs 411 | 412 | ##### add your solution here 413 | 414 | $ cat pets.txt 415 | cats 416 | parrots 417 | dogs 418 | $ cat bkp/pets.txt 419 | I like cats 420 | I like parrots 421 | I like dogs 422 | ``` 423 | 424 |
425 | 426 | # Field separators 427 | 428 | **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. 429 | 430 | ```bash 431 | $ cat brackets.txt 432 | foo blah blah(ice) 123 xyz$ 433 | (almond-pista) choco 434 | yo )yoyo( yo 435 | 436 | ##### add your solution here 437 | ice 438 | almond-pista 439 | yoyo 440 | ``` 441 | 442 | **2)** For the input file `scores.csv`, extract `Name` and `Physics` fields in the format shown below. 443 | 444 | ```bash 445 | $ cat scores.csv 446 | Name,Maths,Physics,Chemistry 447 | Blue,67,46,99 448 | Lin,78,83,80 449 | Er,56,79,92 450 | Cy,97,98,95 451 | Ort,68,72,66 452 | Ith,100,100,100 453 | 454 | ##### add your solution here 455 | Name:Physics 456 | Blue:46 457 | Lin:83 458 | Er:79 459 | Cy:98 460 | Ort:72 461 | Ith:100 462 | ``` 463 | 464 | **3)** For the input file `scores.csv`, display names of those who've scored above `80` in Maths. 465 | 466 | ```bash 467 | ##### add your solution here 468 | Cy 469 | Ith 470 | ``` 471 | 472 | **4)** Display the number of word characters for the given inputs. Word definition here is same as used in regular expressions. Can you construct two different solutions as indicated below? 473 | 474 | ```bash 475 | # solve using the 's' operator 476 | $ echo 'hi there' | ##### add your solution here 477 | 7 478 | 479 | # solve without using the substitution or transliteration operators 480 | $ echo 'u-no;co%."(do_12:as' | ##### add your solution here 481 | 12 482 | ``` 483 | 484 | **5)** For the input file `quoted.txt`, extract the sequence of characters surrounded by double quotes and display them in the format shown below. 485 | 486 | ```bash 487 | $ cat quoted.txt 488 | 1 "grape" and "mango" and "guava" 489 | ("c 1""d""a-2""b") 490 | 491 | ##### add your solution here 492 | "grape","guava","mango" 493 | "a-2","b","c 1","d" 494 | ``` 495 | 496 | **6)** Display only the third and fifth characters from each input line as shown below. 497 | 498 | ```bash 499 | $ printf 'restore\ncat one\ncricket' | ##### add your solution here 500 | so 501 | to 502 | ik 503 | ``` 504 | 505 | **7)** Transform the given input file `fw.txt` to get the output as shown below. If a field is empty (i.e. contains only space characters), replace it with `NA`. 506 | 507 | ```bash 508 | $ cat fw.txt 509 | 1.3 rs 90 0.134563 510 | 3.8 6 511 | 5.2 ye 8.2387 512 | 4.2 kt 32 45.1 513 | 514 | ##### add your solution here 515 | 1.3,rs,0.134563 516 | 3.8,NA,6 517 | 5.2,ye,8.2387 518 | 4.2,kt,45.1 519 | ``` 520 | 521 | **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. 522 | 523 | ```bash 524 | ##### add your solution here 525 | Name,Maths,Physics,Chemistry 526 | Blue,67,46,99 527 | Ort,68,72,66 528 | Ith,100,100,100 529 | ``` 530 | 531 | **9)** Extract all whole words containing `42` but not at the edge of a word. Assume a word cannot contain `42` more than once. 532 | 533 | ```bash 534 | $ s='hi42bye nice1423 bad42 cool_42a 42fake' 535 | $ echo "$s" | ##### add your solution here 536 | hi42bye 537 | nice1423 538 | cool_42a 539 | ``` 540 | 541 | **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. 542 | 543 | ```bash 544 | ##### add your solution here 545 | Name,Maths,Physics,Chemistry,GP 546 | Blue,67,46,99,69.75 547 | Lin,78,83,80,79.75 548 | Er,56,79,92,70.75 549 | Cy,97,98,95,96.75 550 | Ort,68,72,66,68.5 551 | Ith,100,100,100,100 552 | ``` 553 | 554 | **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. 555 | 556 | ```bash 557 | $ cat mixed_fs.txt 558 | rose lily jasmine tulip 559 | pink blue white yellow 560 | car,mat,ball,basket 561 | light green,brown,black,purple 562 | apple,banana,cherry 563 | 564 | ##### add your solution here 565 | rose lily 566 | pink blue 567 | car,mat 568 | light green,brown 569 | apple,banana 570 | ``` 571 | 572 | **12)** For the given space separated numbers, filter only numbers in the range `20` to `1000` (inclusive). 573 | 574 | ```bash 575 | $ s='20 -983 5 756 634223 1000' 576 | 577 | $ echo "$s" | ##### add your solution here 578 | 20 756 1000 579 | ``` 580 | 581 | **13)** For the given input file `words.txt`, filter all lines containing characters in ascending and descending order. 582 | 583 | ```bash 584 | $ cat words.txt 585 | bot 586 | art 587 | are 588 | boat 589 | toe 590 | flee 591 | reed 592 | 593 | # ascending order 594 | ##### add your solution here 595 | bot 596 | art 597 | 598 | # descending order 599 | ##### add your solution here 600 | toe 601 | reed 602 | ``` 603 | 604 | **14)** For the given space separated words, extract the three longest words. 605 | 606 | ```bash 607 | $ s='I bought two bananas and three mangoes' 608 | 609 | $ echo "$s" | ##### add your solution here 610 | bananas 611 | mangoes 612 | bought 613 | ``` 614 | 615 | **15)** Convert the contents of `split.txt` as shown below. 616 | 617 | ```bash 618 | $ cat split.txt 619 | apple,1:2:5,mango 620 | wry,4,look 621 | pencil,3:8,paper 622 | 623 | ##### add your solution here 624 | apple,1,mango 625 | apple,2,mango 626 | apple,5,mango 627 | wry,4,look 628 | pencil,3,paper 629 | pencil,8,paper 630 | ``` 631 | 632 | **16)** Generate string combinations as shown below for the given input string passed as an environment variable. 633 | 634 | ```bash 635 | $ s='{x,y,z}{1,2,3}' ##### add your solution here 636 | x1 x2 x3 y1 y2 y3 z1 z2 z3 637 | ``` 638 | 639 | **17)** For the input file `varying_fields.txt`, construct a solution to get the output shown below. 640 | 641 | ```bash 642 | $ cat varying_fields.txt 643 | hi,bye,there,was,here,to 644 | 1,2,3,4,5 645 | 646 | ##### add your solution here 647 | hi:bye:to 648 | 1:2:5 649 | ``` 650 | 651 | **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 `s` operator. 652 | 653 | ```bash 654 | $ cat fields.txt 655 | 42:cat 656 | twelve:a2b 657 | we:be:he:0:a:b:bother 658 | apple:banana-42:cherry: 659 | dragon:unicorn:centaur 660 | 661 | ##### add your solution here 662 | 42 663 | twelve:a2b 664 | we:be:he:0:a:b 665 | apple:banana-42:cherry 666 | dragon:unicorn:centaur 667 | ``` 668 | 669 | **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. 670 | 671 | ```bash 672 | $ s='applecatfigCaT12345cAtbanana' 673 | $ echo "$s" | ##### add your solution here 674 | apple fig 12345 banana 42 675 | ``` 676 | 677 | **20)** For the input file `sample.txt`, filter lines containing 5 or more lowercase vowels. 678 | 679 | ```bash 680 | ##### add your solution here 681 | How are you 682 | Believe it 683 | No doubt you like it too 684 | Much ado about nothing 685 | ``` 686 | 687 |
688 | 689 | # Record separators 690 | 691 | **1)** The input file `jumbled.txt` consists of words separated by various delimiters. Display all words that contain `an` or `at` or `in` or `it`, one per line. 692 | 693 | ```bash 694 | $ cat jumbled.txt 695 | overcoats;furrowing-typeface%pewter##hobby 696 | wavering:concession/woof\retailer 697 | joint[]seer{intuition}titanic 698 | 699 | ##### add your solution here 700 | overcoats 701 | furrowing 702 | wavering 703 | joint 704 | intuition 705 | titanic 706 | ``` 707 | 708 | **2)** Emulate `paste -sd,` with Perl. 709 | 710 | ```bash 711 | # this command joins all input lines with the ',' character 712 | $ paste -sd, ip.txt 713 | Hello World,How are you,This game is good,Today is sunny,12345,You are funny 714 | # make sure there's no ',' at the end of the line 715 | # and that there's a newline character at the end of the line 716 | ##### add your solution here 717 | Hello World,How are you,This game is good,Today is sunny,12345,You are funny 718 | 719 | # if there's only one line in input, again make sure there's no trailing ',' 720 | # and that there's a newline character at the end of the line 721 | $ printf 'fig' | paste -sd, 722 | fig 723 | $ printf 'fig' | ##### add your solution here 724 | fig 725 | ``` 726 | 727 | **3)** For the input file `sample.txt`, extract all paragraphs having words starting with `do`. 728 | 729 | ```bash 730 | $ cat sample.txt 731 | Hello World 732 | 733 | Good day 734 | How are you 735 | 736 | Just do-it 737 | Believe it 738 | 739 | Today is sunny 740 | Not a bit funny 741 | No doubt you like it too 742 | 743 | Much ado about nothing 744 | He he he 745 | 746 | # note that there's no extra empty line at the end of the output 747 | ##### add your solution here 748 | Just do-it 749 | Believe it 750 | 751 | Today is sunny 752 | Not a bit funny 753 | No doubt you like it too 754 | ``` 755 | 756 | **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. 757 | 758 | ```bash 759 | # note that there's no extra empty line at the end of the output 760 | ##### add your solution here 761 | Hello World. 762 | 763 | Good day. How are you. 764 | 765 | Just do-it. Believe it. 766 | 767 | Today is sunny. Not a bit funny. No doubt you like it too. 768 | 769 | Much ado about nothing. He he he. 770 | ``` 771 | 772 | **5)** For the given input, use `;;` as the record separators and `:` as the field separators. Filter records whose second field is greater than `50`. 773 | 774 | ```bash 775 | $ s='mango:100;;apple:25;;grapes:75' 776 | 777 | # note that the output has ;; at the end, not a newline character 778 | $ printf "$s" | ##### add your solution here 779 | mango:100;;grapes:75;; 780 | ``` 781 | 782 | **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 the empty lines at the start and end of the file. 783 | 784 | ```bash 785 | ##### add your solution here 786 | hello 787 | 788 | 789 | world 790 | 791 | 792 | apple 793 | banana 794 | cherry 795 | 796 | 797 | tea coffee 798 | chocolate 799 | ``` 800 | 801 | **7)** The sample string shown below uses `cat` as the record separator. Display only the even numbered records separated by a single empty line. 802 | 803 | ```bash 804 | $ s='applecatfigcat12345catbananacatguava:cat:mangocat3' 805 | $ echo "$s" | ##### add your solution here 806 | fig 807 | 808 | banana 809 | 810 | :mango 811 | ``` 812 | 813 |
814 | 815 | # Using modules 816 | 817 | **1)** For the given space separated words, display the max word determined by alphabetic order. 818 | 819 | ```bash 820 | $ s='let in bat xml me lion' 821 | 822 | $ echo "$s" | ##### add your solution here 823 | xml 824 | ``` 825 | 826 | **2)** For the given space separated words, randomize the order of characters for each word. 827 | 828 | ```bash 829 | $ s='this is a sample sentence' 830 | 831 | # sample randomized output shown here, could be different for you 832 | $ echo "$s" | ##### add your solution here 833 | htis si a melasp ecnnsete 834 | ``` 835 | 836 | **3)** Use the [metacpan: XML::LibXML](https://metacpan.org/pod/XML::LibXML) module to get the content of all tags named `blue` for the input file `sample.xml`. See [grantm: Perl XML::LibXML by example](https://grantm.github.io/perl-libxml-by-example/) for a detailed book on the `XML::LibXML` module. 837 | 838 | ```bash 839 | $ cat sample.xml 840 | 841 | Hi there. How are you? 842 | I am good. 843 | 844 | flower 845 | sand stone 846 | sky 847 | water 848 | 849 | 850 | 851 | ##### add your solution here 852 | flower 853 | sand stone 854 | ``` 855 | 856 | **4)** Display the current time in the format shown below. 857 | 858 | ```bash 859 | # output will be different for you 860 | ##### add your solution here 861 | 12-Sep-2023 11:01:14 862 | ``` 863 | 864 | >![info](../images/info.svg) See [metacpan: DateTime](https://metacpan.org/pod/DateTime) for more comprehensive functions. 865 | 866 |
867 | 868 | # Multiple file input 869 | 870 | **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. 871 | 872 | ```bash 873 | # assume table.txt ip.txt are passed as file inputs 874 | ##### add your solution here 875 | >table.txt< 876 | 42 877 | -7 878 | ---------- 879 | >ip.txt< 880 | World 881 | you 882 | ---------- 883 | ``` 884 | 885 | **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. 886 | 887 | ```bash 888 | ##### add your solution here 889 | secrets.txt 890 | ip.txt 891 | table.txt 892 | ``` 893 | 894 | **3)** Print the first 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. 895 | 896 | ```bash 897 | ##### add your solution here 898 | Hello World 899 | How are you 900 | --- 901 | Hello World 902 | 903 | --- 904 | brown bread mat hair 42 905 | blue cake mug shirt -7 906 | ``` 907 | 908 | **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. 909 | 910 | ```bash 911 | ##### add your solution here 912 | game 913 | day 914 | bla 915 | ``` 916 | 917 |
918 | 919 | # Processing multiple records 920 | 921 | **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`. 922 | 923 | ```bash 924 | ##### add your solution here 925 | Just do-it 926 | Much ado about nothing 927 | ``` 928 | 929 | **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). 930 | 931 | ```bash 932 | # for reference, here are all the matches 933 | $ grep -i 'do' sample.txt 934 | Just do-it 935 | No doubt you like it too 936 | Much ado about nothing 937 | $ grep -i 'not' sample.txt 938 | Not a bit funny 939 | Much ado about nothing 940 | 941 | ##### add your solution here 942 | No doubt you like it too 943 | Much ado about nothing 944 | ``` 945 | 946 | **3)** For the input file `sample.txt`, print the matching line as well as `n` lines around the matching lines. The value for `n` is passed to the Perl command as an environment value. 947 | 948 | ```bash 949 | # match a line containing 'are' or 'bit' 950 | $ n=1 ##### add your solution here 951 | Good day 952 | How are you 953 | 954 | Today is sunny 955 | Not a bit funny 956 | No doubt you like it too 957 | 958 | # match a line containing 'World' 959 | $ n=2 ##### add your solution here 960 | Hello World 961 | 962 | Good day 963 | ``` 964 | 965 | **4)** For the input file `broken.txt`, print all lines between the markers `top` and `bottom`. The first Perl 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. 966 | 967 | ```bash 968 | $ cat broken.txt 969 | top 970 | 3.14 971 | bottom 972 | --- 973 | top 974 | 1234567890 975 | bottom 976 | top 977 | Hi there 978 | Have a nice day 979 | Good bye 980 | 981 | # wrong output 982 | $ perl -ne '$f=0 if /bottom/; print if $f; $f=1 if /top/' broken.txt 983 | 3.14 984 | 1234567890 985 | Hi there 986 | Have a nice day 987 | Good bye 988 | 989 | # expected output 990 | ##### add your solution here 991 | 3.14 992 | 1234567890 993 | ``` 994 | 995 | **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. 996 | 997 | ```bash 998 | $ cat concat.txt 999 | %%% addr.txt 1000 | How are you 1001 | This game is good 1002 | Today %%% is sunny 1003 | %%% broken.txt 1004 | top %%% 1005 | 1234567890 1006 | bottom 1007 | %%% sample.txt 1008 | Just %%% do-it 1009 | Believe it 1010 | %%% mixed_fs.txt 1011 | pink blue white yellow 1012 | car,mat,ball,basket 1013 | 1014 | $ n=2 ##### add your solution here 1015 | %%% broken.txt 1016 | top %%% 1017 | 1234567890 1018 | bottom 1019 | 1020 | $ n=4 ##### add your solution here 1021 | %%% mixed_fs.txt 1022 | pink blue white yellow 1023 | car,mat,ball,basket 1024 | ``` 1025 | 1026 | **6)** For the input file `perl.md`, replace all occurrences of `perl` (irrespective of case) with `Perl`. But, do not replace any matches between ` ```perl ` and ` ``` ` lines (`perl` in these markers shouldn't be replaced either). Save the output in `out.md`. 1027 | 1028 | ```bash 1029 | ##### add your solution here, redirect the output to 'out.md' 1030 | 1031 | $ diff -sq out.md expected.md 1032 | Files out.md and expected.md are identical 1033 | ``` 1034 | 1035 | **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. 1036 | 1037 | ```bash 1038 | ##### add your solution here 1039 | 12345 1040 | You are funny 1041 | --- 1042 | Much ado about nothing 1043 | He he he 1044 | --- 1045 | blue cake mug shirt -7 1046 | yellow banana window shoes 3.14 1047 | ``` 1048 | 1049 | **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. 1050 | 1051 | ```bash 1052 | $ cat lines.txt 1053 | Go There 1054 | come on 1055 | go there 1056 | --- 1057 | 2 apples and 5 mangoes 1058 | come on! 1059 | --- 1060 | 2 Apples 1061 | COME ON 1062 | 1063 | ##### add your solution here 1064 | Go There 1065 | come on 1066 | go there 1067 | --- 1068 | come on! 1069 | --- 1070 | COME ON 1071 | ``` 1072 | 1073 | **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. 1074 | 1075 | ```bash 1076 | $ cat result.csv 1077 | Amy,maths,89 1078 | Amy,physics,75 1079 | Joe,maths,79 1080 | John,chemistry,77 1081 | John,physics,91 1082 | Moe,maths,81 1083 | Ravi,physics,84 1084 | Ravi,chemistry,70 1085 | Yui,maths,92 1086 | 1087 | ##### add your solution here 1088 | Amy,maths,89 1089 | Amy,physics,75 1090 | --- 1091 | Joe,maths,79 1092 | --- 1093 | John,chemistry,77 1094 | John,physics,91 1095 | --- 1096 | Moe,maths,81 1097 | --- 1098 | Ravi,physics,84 1099 | Ravi,chemistry,70 1100 | --- 1101 | Yui,maths,92 1102 | ``` 1103 | 1104 |
1105 | 1106 | # Two file processing 1107 | 1108 | **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`. 1109 | 1110 | ```bash 1111 | $ cat match_words.txt 1112 | %whole(Hello)--{doubt}==ado== 1113 | just,\joint*,concession<=nice 1114 | 1115 | # 'concession' is one of the third words from 'match_words.txt' 1116 | # and second word from 'jumbled.txt' 1117 | ##### add your solution here 1118 | wavering:concession/woof\retailer 1119 | No doubt you like it too 1120 | ``` 1121 | 1122 | **2)** Interleave the contents of `secrets.txt` with the contents of a file passed as stdin in the format as shown below. 1123 | 1124 | ```bash 1125 | ##### add your solution here, use 'table.txt' for stdin data 1126 | stag area row tick 1127 | brown bread mat hair 42 1128 | --- 1129 | deaf chi rate tall glad 1130 | blue cake mug shirt -7 1131 | --- 1132 | Bi tac toe - 42 1133 | yellow banana window shoes 3.14 1134 | ``` 1135 | 1136 | **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). 1137 | 1138 | ```bash 1139 | $ cat search_terms.txt 1140 | hello 1141 | row 1142 | you 1143 | is 1144 | at 1145 | 1146 | # ip: search_terms.txt jumbled.txt mixed_fs.txt secrets.txt table.txt oops.txt 1147 | ##### add your solution here 1148 | row 1149 | at 1150 | 1151 | # ip: search_terms.txt ip.txt sample.txt oops.txt 1152 | ##### add your solution here 1153 | hello 1154 | you 1155 | is 1156 | ``` 1157 | 1158 | **4)** Replace the third to fifth lines of the input file `ip.txt` with the second to fourth lines from the file `para.txt`. 1159 | 1160 | ```bash 1161 | ##### add your solution here 1162 | Hello World 1163 | How are you 1164 | Start working on that 1165 | project you always wanted 1166 | to, do not let it end 1167 | You are funny 1168 | ``` 1169 | 1170 | **5)** Insert one line from `jumbled.txt` before every two lines of `copyright.txt`. 1171 | 1172 | ```bash 1173 | ##### add your solution here 1174 | overcoats;furrowing-typeface%pewter##hobby 1175 | bla bla 2015 bla 1176 | blah 2018 blah 1177 | wavering:concession/woof\retailer 1178 | bla bla bla 1179 | copyright: 2020 1180 | ``` 1181 | 1182 | **6)** 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. 1183 | 1184 | ```bash 1185 | $ cat match.txt 1186 | print this 1187 | but not that 1188 | $ cat error.txt 1189 | print this 1190 | but not that or this 1191 | print this 1192 | but not that 1193 | if print this 1194 | but not that 1195 | print this 1196 | but not that 1197 | 1198 | ##### add your solution here 1199 | print this 1200 | but not that or this 1201 | overcoats;furrowing-typeface%pewter##hobby 1202 | wavering:concession/woof\retailer 1203 | joint[]seer{intuition}titanic 1204 | if print this 1205 | but not that 1206 | overcoats;furrowing-typeface%pewter##hobby 1207 | wavering:concession/woof\retailer 1208 | joint[]seer{intuition}titanic 1209 | ``` 1210 | 1211 | **7)** 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. 1212 | 1213 | ```bash 1214 | $ cat names.txt 1215 | Lin 1216 | Cy 1217 | Ith 1218 | 1219 | ##### add your solution here 1220 | Lin 78 83 80 1221 | Cy 97 98 95 1222 | Ith 100 100 100 1223 | ``` 1224 | 1225 | **8)** 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. 1226 | 1227 | ```bash 1228 | $ cat result.csv 1229 | Amy,maths,89 1230 | Amy,physics,75 1231 | Joe,maths,79 1232 | John,chemistry,77 1233 | John,physics,91 1234 | Moe,maths,81 1235 | Ravi,physics,84 1236 | Ravi,chemistry,70 1237 | Yui,maths,92 1238 | 1239 | $ cat criteria.txt 1240 | Amy maths 1241 | John chemistry 1242 | John physics 1243 | Ravi chemistry 1244 | Yui maths 1245 | 1246 | ##### add your solution here 1247 | Amy,maths,89 1248 | John,physics,91 1249 | Yui,maths,92 1250 | ``` 1251 | 1252 | **9)** Insert the contents of `hex.txt` before a line matching `cake` of the input file `table.txt` 1253 | 1254 | ```bash 1255 | ##### add your solution here 1256 | brown bread mat hair 42 1257 | start: 0xA0, func1: 0xA0 1258 | end: 0xFF, func2: 0xB0 1259 | restart: 0xA010, func3: 0x7F 1260 | blue cake mug shirt -7 1261 | yellow banana window shoes 3.14 1262 | ``` 1263 | 1264 | **10)** For the input file `ip.txt`, replace lines containing `are` with the contents of `hex.txt`. 1265 | 1266 | ```bash 1267 | ##### add your solution here 1268 | Hello World 1269 | start: 0xA0, func1: 0xA0 1270 | end: 0xFF, func2: 0xB0 1271 | restart: 0xA010, func3: 0x7F 1272 | This game is good 1273 | Today is sunny 1274 | 12345 1275 | start: 0xA0, func1: 0xA0 1276 | end: 0xFF, func2: 0xB0 1277 | restart: 0xA010, func3: 0x7F 1278 | ``` 1279 | 1280 |
1281 | 1282 | # Dealing with duplicates 1283 | 1284 | **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. 1285 | 1286 | ```bash 1287 | $ cat lines.txt 1288 | Go There 1289 | come on 1290 | go there 1291 | --- 1292 | 2 apples and 5 mangoes 1293 | come on! 1294 | --- 1295 | 2 Apples 1296 | COME ON 1297 | 1298 | ##### add your solution here 1299 | Go There 1300 | come on 1301 | --- 1302 | 2 apples and 5 mangoes 1303 | come on! 1304 | 2 Apples 1305 | ``` 1306 | 1307 | **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. 1308 | 1309 | ```bash 1310 | $ cat twos.txt 1311 | hehe haha 1312 | door floor 1313 | haha hehe 1314 | 6;8 3-4 1315 | true blue 1316 | hehe bebe 1317 | floor door 1318 | 3-4 6;8 1319 | tru eblue 1320 | haha hehe 1321 | 1322 | ##### add your solution here 1323 | hehe haha 1324 | door floor 1325 | 6;8 3-4 1326 | true blue 1327 | hehe bebe 1328 | tru eblue 1329 | ``` 1330 | 1331 | **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. 1332 | 1333 | ```bash 1334 | ##### add your solution here 1335 | true blue 1336 | hehe bebe 1337 | tru eblue 1338 | ``` 1339 | 1340 |
1341 | 1342 | # Perl rename command 1343 | 1344 | **1)** Determine and implement the rename logic based on the filenames and expected output shown below. 1345 | 1346 | ```bash 1347 | $ touch ' (2020) Report part 1 . txt ' 'analysis Part 3 (2018) .log' 1348 | 1349 | ##### add your solution here 1350 | 1351 | $ ls 1352 | 2020_report_part_1.txt analysis_part_3_2018.log 1353 | ``` 1354 | 1355 | **2)** See [unix.stackexchange: rename Q&A sorted by votes](https://unix.stackexchange.com/questions/tagged/rename?tab=Votes) for further reading as well as a source for exercises. 1356 | 1357 | -------------------------------------------------------------------------------- /exercises/brackets.txt: -------------------------------------------------------------------------------- 1 | foo blah blah(ice) 123 xyz$ 2 | (almond-pista) choco 3 | yo )yoyo( yo 4 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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/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/expected.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | For text processing, Perl is very handy. 4 | 5 | ```perl 6 | $ perl -e 'print "Hello Perl\n"' 7 | Hello Perl 8 | 9 | $ printf 'gate\napple\nwhat\nkite\n' | perl -ne 'print if !/e/' 10 | what 11 | ``` 12 | 13 | ## Field processing 14 | 15 | Perl comes loaded with awesome cli options. Enjoy learning Perl. 16 | 17 | ```perl 18 | $ s='goal:amazing:whistle:kwality' 19 | $ echo "$s" | perl -F: -lane 'print join "-", @F[-1, 1, 0]' 20 | kwality-amazing-goal 21 | ``` 22 | 23 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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/hex.txt: -------------------------------------------------------------------------------- 1 | start: 0xA0, func1: 0xA0 2 | end: 0xFF, func2: 0xB0 3 | restart: 0xA010, func3: 0x7F 4 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /exercises/match.txt: -------------------------------------------------------------------------------- 1 | print this 2 | but not that 3 | -------------------------------------------------------------------------------- /exercises/match_words.txt: -------------------------------------------------------------------------------- 1 | %whole(Hello)--{doubt}==ado== 2 | just,\joint*,concession<=nice 3 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /exercises/names.txt: -------------------------------------------------------------------------------- 1 | Lin 2 | Cy 3 | Ith 4 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /exercises/out.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | For text processing, Perl is very handy. 4 | 5 | ```perl 6 | $ perl -e 'print "Hello Perl\n"' 7 | Hello Perl 8 | 9 | $ printf 'gate\napple\nwhat\nkite\n' | perl -ne 'print if !/e/' 10 | what 11 | ``` 12 | 13 | ## Field processing 14 | 15 | Perl comes loaded with awesome cli options. Enjoy learning Perl. 16 | 17 | ```perl 18 | $ s='goal:amazing:whistle:kwality' 19 | $ echo "$s" | perl -F: -lane 'print join "-", @F[-1, 1, 0]' 20 | kwality-amazing-goal 21 | ``` 22 | 23 | -------------------------------------------------------------------------------- /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/perl.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | For text processing, PERL is very handy. 4 | 5 | ```perl 6 | $ perl -e 'print "Hello Perl\n"' 7 | Hello Perl 8 | 9 | $ printf 'gate\napple\nwhat\nkite\n' | perl -ne 'print if !/e/' 10 | what 11 | ``` 12 | 13 | ## Field processing 14 | 15 | perl comes loaded with awesome cli options. Enjoy learning PeRl. 16 | 17 | ```perl 18 | $ s='goal:amazing:whistle:kwality' 19 | $ echo "$s" | perl -F: -lane 'print join "-", @F[-1, 1, 0]' 20 | kwality-amazing-goal 21 | ``` 22 | 23 | -------------------------------------------------------------------------------- /exercises/pets.txt: -------------------------------------------------------------------------------- 1 | I like cats 2 | I like parrots 3 | I like dogs 4 | -------------------------------------------------------------------------------- /exercises/quoted.txt: -------------------------------------------------------------------------------- 1 | 1 "grape" and "mango" and "guava" 2 | ("c 1""d""a-2""b") 3 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /exercises/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/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/search_terms.txt: -------------------------------------------------------------------------------- 1 | hello 2 | row 3 | you 4 | is 5 | at 6 | -------------------------------------------------------------------------------- /exercises/secrets.txt: -------------------------------------------------------------------------------- 1 | stag area row tick 2 | deaf chi rate tall glad 3 | Bi tac toe - 42 4 | -------------------------------------------------------------------------------- /exercises/split.txt: -------------------------------------------------------------------------------- 1 | apple,1:2:5,mango 2 | wry,4,look 3 | pencil,3:8,paper 4 | -------------------------------------------------------------------------------- /exercises/table.txt: -------------------------------------------------------------------------------- 1 | brown bread mat hair 42 2 | blue cake mug shirt -7 3 | yellow banana window shoes 3.14 4 | -------------------------------------------------------------------------------- /exercises/text.txt: -------------------------------------------------------------------------------- 1 | can ran want plant 2 | tin fin fit mine line 3 | -------------------------------------------------------------------------------- /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/varying_fields.txt: -------------------------------------------------------------------------------- 1 | hi,bye,there,was,here,to 2 | 1,2,3,4,5 3 | -------------------------------------------------------------------------------- /exercises/words.txt: -------------------------------------------------------------------------------- 1 | bot 2 | art 3 | are 4 | boat 5 | toe 6 | flee 7 | reed 8 | -------------------------------------------------------------------------------- /images/info.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/perl_oneliners_ls.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/learnbyexample/learn_perl_oneliners/304ce140762eed995e81077e7789961f0fc9e023/images/perl_oneliners_ls.png -------------------------------------------------------------------------------- /images/warning.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /sample_chapters/perl_oneliners_sample.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/learnbyexample/learn_perl_oneliners/304ce140762eed995e81077e7789961f0fc9e023/sample_chapters/perl_oneliners_sample.pdf --------------------------------------------------------------------------------