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