This shows you the differences between two versions of the page.
Next revision | Previous revision | ||
haas:spring2017:unix:projects:usf0 [2017/03/12 19:35] – created wedge | haas:spring2017:unix:projects:usf0 [2017/03/13 15:05] (current) – [Specifications] wedge | ||
---|---|---|---|
Line 171: | Line 171: | ||
You'll notice that everything lines up and is positioned similarly: | You'll notice that everything lines up and is positioned similarly: | ||
- | * each column exists within 8 characters of on-screen real estate, with one addition | + | * each column exists within 8 characters of on-screen real estate, with one additional |
* The values are right justified with each column, with all bases but decimal being exactly the same length (prepending leading zeroes if necessary) | * The values are right justified with each column, with all bases but decimal being exactly the same length (prepending leading zeroes if necessary) | ||
* The dashes and vertical bars set up an ASCII art-like table pattern that helps make the data more readable. | * The dashes and vertical bars set up an ASCII art-like table pattern that helps make the data more readable. | ||
Line 192: | Line 192: | ||
Fear not! The **printf(1)** tool comes to your rescue! | Fear not! The **printf(1)** tool comes to your rescue! | ||
- | Like **echo**, **printf** displays information to the screen (STDOUT). In fact, various programming languages that want more powerful output formatting implement some form of printf into their vast libraries. | + | Like **echo**, **printf** displays information to the screen (STDOUT). In fact, various programming languages |
Be sure to check the manual page for options and functionality; | Be sure to check the manual page for options and functionality; | ||
+ | ===Basic operation=== | ||
+ | |||
+ | Like **echo**, **printf** in its simplest form takes as an argument a string to display to STDOUT: | ||
+ | |||
+ | <cli> | ||
+ | lab46: | ||
+ | Hello, Worldlab46: | ||
+ | </ | ||
+ | |||
+ | However, we notice one difference between the default behavior of **printf** vs. **echo**: **printf** does not automatically issue a newline by default, as **echo** does. So, we'll need to specify it manually with the **\n** character: | ||
+ | |||
+ | <cli> | ||
+ | lab46: | ||
+ | Hello, World | ||
+ | lab46: | ||
+ | </ | ||
+ | |||
+ | Those various escape characters we've learned about? Super useful here: | ||
+ | |||
+ | * **\n** - newline | ||
+ | * **\t** - tab | ||
+ | |||
+ | Be sure to check the manual page for additional escape characters. | ||
+ | |||
+ | ===Format specifiers=== | ||
+ | Now, we know from using **echo** we can utilize shell variable and command expansions to make our output more dynamic. | ||
+ | |||
+ | But, **printf** adds additional formatting capability that **echo** lacks. If the string we are displaying contains **%** symbols, substitutions can be made and behaviors invoked; functionality that **echo** lacks. | ||
+ | |||
+ | Some common format specifiers: | ||
+ | |||
+ | * **%d** - substitute integer (whole number) value | ||
+ | * **%s** - substitute string value | ||
+ | * **%c** - substitute single character | ||
+ | * **%f** - substitute floating point value | ||
+ | * **%o** - substitute integer (whole number) value and represent in octal | ||
+ | * **%x** - substitute integer (whole number) value and represent in hexadecimal | ||
+ | |||
+ | First up, a simple example: | ||
+ | |||
+ | <cli> | ||
+ | lab46: | ||
+ | 175 | ||
+ | lab46: | ||
+ | </ | ||
+ | |||
+ | Then, adding to it: | ||
+ | |||
+ | <cli> | ||
+ | lab46: | ||
+ | The number: 175 | ||
+ | lab46: | ||
+ | </ | ||
+ | |||
+ | That 175 can also be in a variable: | ||
+ | |||
+ | <cli> | ||
+ | lab46: | ||
+ | lab46: | ||
+ | The number: 175 | ||
+ | lab46: | ||
+ | </ | ||
+ | |||
+ | You may want to wrap the variable in double quotes, to avoid cases where it might be NULL and otherwise generate an error (I generally quote all my variables to be on the safe side). | ||
+ | |||
+ | How about substitutions with strings? | ||
+ | |||
+ | <cli> | ||
+ | lab46: | ||
+ | Your username is: username | ||
+ | lab46: | ||
+ | </ | ||
+ | |||
+ | And in general just crafting super effective format strings: | ||
+ | |||
+ | <cli> | ||
+ | lab46: | ||
+ | lab46: | ||
+ | 175 is hexadecimal AF | ||
+ | lab46: | ||
+ | </ | ||
+ | |||
+ | Please take note, where there are multiple format specifiers, substitution is in order of specification... **%d** was the first, **%s** was the second, and **%X** was the third in that particular string, so the first value following the string is grabbed by the **%d**, the next the **%s**, and the third the **%X**. Ordering matters (which should make sense). | ||
+ | |||
+ | ===Output formatting=== | ||
+ | So now, getting to where **printf** really excels, formatting your output. | ||
+ | |||
+ | It turns out, that between the **%** and whatever format option you specify, you can provide a numeric value which will impact how that number appears on the screen, commonly in the form of preallocated space to display within. | ||
+ | |||
+ | For instance: | ||
+ | |||
+ | <cli> | ||
+ | lab46: | ||
+ | Testing: >> | ||
+ | lab46: | ||
+ | </ | ||
+ | |||
+ | See what happened there? 47 was displayed, but WITHIN a block of 4 characters. Also of note, by default output is **right justified**. | ||
+ | |||
+ | To **left** justify, simply make it negative: | ||
+ | |||
+ | <cli> | ||
+ | lab46: | ||
+ | Testing: >> | ||
+ | lab46: | ||
+ | </ | ||
+ | |||
+ | We can also pad with zeros, that is represented by decimal values: | ||
+ | |||
+ | <cli> | ||
+ | lab46: | ||
+ | Testing: >> | ||
+ | lab46: | ||
+ | </ | ||
+ | |||
+ | This can be combined with justify and space allocation: | ||
+ | |||
+ | <cli> | ||
+ | lab46: | ||
+ | Testing: >> | ||
+ | lab46: | ||
+ | </ | ||
+ | |||
+ | Other neat tricks? We can variable-ize the padding by using a **< | ||
+ | |||
+ | <cli> | ||
+ | lab46: | ||
+ | lab46: | ||
+ | Testing: >> | ||
+ | lab46: | ||
+ | </ | ||
+ | |||
+ | The **printf** tool is super-powerful and useful for output, so mastering its use adds an impressive capability to your repertoire. | ||
+ | |||
+ | Play with **printf** and experiment... you'll find it can accomplish some impressive output feats that previously may have been more complicated. | ||
=====Submission===== | =====Submission===== | ||
By successfully performing this project, you should have a fully functioning script by the name of **usf0.sh**, | By successfully performing this project, you should have a fully functioning script by the name of **usf0.sh**, | ||
Line 214: | Line 349: | ||
< | < | ||
- | 78:upf1:final tally of results (78/78) | + | 78:usf0:final tally of results (78/78) |
- | *:upf1:upf1steps | + | *:usf0:usf0.sh |
- | *:upf1:upf1steps covers steps from copy until submit [4/4] | + | *:usf0:usf0.sh has a shabang invoking bash [3/3] |
- | *: | + | *:usf0:usf0.sh runs without error [6/6] |
- | *: | + | *:usf0:usf0.sh with no arguments displays default table [6/6] |
- | *: | + | *:usf0:usf0.sh is commented explaining implementation |
- | *:upf1:task0.cli uses specified input_value | + | *:usf0:table heading and separators conform to project specifications |
- | *:upf1:task0.cli uses specified input_unit | + | *:usf0:values are calculated, not literally displayed |
- | *:upf1:task0.cli solution in specified output_unit | + | *:usf0:binary column is correct |
- | *:upf1:task0.cli solution using specified precision | + | *:usf0:octal column is correct |
- | *:upf1:task0.cli solution using specified delimiter | + | *:usf0:decimal column is correct |
- | *:upf1:task1.cli produces | + | *:usf0:hexadecimal column is correct |
- | *:upf1:task1.cli uses specified input_value [1/1] | + | *:usf0:starting value is properly checked for and verified |
- | *: | + | *:usf0:ending value is properly checked for and verified |
- | *: | + | *:usf0:signed option is properly checked for and verified |
- | *: | + | |
- | *: | + | |
- | *: | + | |
- | *:upf1:task2.cli uses specified input_value [1/1] | + | |
- | *: | + | |
- | *: | + | |
- | *: | + | |
- | *: | + | |
- | *: | + | |
- | *:upf1:task3.cli uses specified input_value [1/1] | + | |
- | *: | + | |
- | *: | + | |
- | *: | + | |
- | *: | + | |
- | *: | + | |
- | *:upf1:task4.cli uses specified input_value | + | |
- | *:upf1:task4.cli uses specified input_unit | + | |
- | *:upf1:task4.cli solution in specified output_unit [2/2] | + | |
- | *: | + | |
- | *: | + | |
- | *: | + | |
- | *: | + | |
- | *: | + | |
- | *: | + | |
- | *: | + | |
- | *: | + | |
- | *: | + | |
- | *: | + | |
- | *: | + | |
- | *: | + | |
- | *: | + | |
- | *: | + | |
- | *: | + | |
- | *: | + | |
- | *: | + | |
- | *: | + | |
- | *: | + | |
- | *: | + | |
</ | </ |