bash:files:read_a_file:read_fields_from_a_file
Differences
This shows you the differences between two versions of the page.
Next revision | Previous revision | ||
bash:files:read_a_file:read_fields_from_a_file [2021/01/26 13:22] – created peter | bash:files:read_a_file:read_fields_from_a_file [2021/01/26 13:44] (current) – [Field splitting, white-space trimming, and other input processing] peter | ||
---|---|---|---|
Line 1: | Line 1: | ||
====== BASH - Files - Read a file - Read fields from a file ====== | ====== BASH - Files - Read a file - Read fields from a file ====== | ||
+ | |||
+ | To read fields within each line of the file, additional variables may be used with the read: | ||
+ | |||
+ | ---- | ||
+ | |||
+ | ===== Fields are separated with white-space (space or tab characters only) ===== | ||
+ | |||
+ | If an input file has 3 columns separated by white-space (space or tab characters only). | ||
+ | |||
+ | <code bash> | ||
+ | while read -r first_name last_name phone; do | ||
+ | # Only print the last name (second column). | ||
+ | printf ' | ||
+ | done < " | ||
+ | </ | ||
+ | |||
+ | ---- | ||
+ | |||
+ | ===== Fields are NOT separated with white-space ===== | ||
+ | |||
+ | If the field delimiters are not whitespace, set the IFS (internal field separator): | ||
+ | |||
+ | <code bash> | ||
+ | # Extract the username and its shell from / | ||
+ | while IFS=: read -r user pass uid gid gecos home shell; do | ||
+ | printf '%s: %s\n' " | ||
+ | done < /etc/passwd | ||
+ | </ | ||
+ | |||
+ | <WRAP info> | ||
+ | **NOTE: | ||
+ | </ | ||
+ | |||
+ | ---- | ||
+ | |||
+ | ===== Tab-delimited files ===== | ||
+ | |||
+ | <WRAP info> | ||
+ | **NOTE: | ||
+ | |||
+ | <WRAP important> | ||
+ | **WARNING: | ||
+ | |||
+ | </ | ||
+ | |||
+ | </ | ||
+ | |||
+ | ---- | ||
+ | |||
+ | ===== Not knowing how many fields a line contains ===== | ||
+ | |||
+ | You do not necessarily need to know how many fields each line of input contains. | ||
+ | |||
+ | * If you supply more variables than there are fields, the extra variables will be empty. | ||
+ | * If you supply fewer, the last variable gets "all the rest" of the fields after the preceding ones are satisfied. | ||
+ | |||
+ | For example: | ||
+ | |||
+ | <code bash> | ||
+ | read -r first last junk <<< | ||
+ | </ | ||
+ | |||
+ | <WRAP info> | ||
+ | **NOTE:** | ||
+ | |||
+ | * **first**: | ||
+ | * **last**: | ||
+ | * **junk**: | ||
+ | |||
+ | </ | ||
+ | |||
+ | ---- | ||
+ | |||
+ | ===== Throwaway variable ===== | ||
+ | |||
+ | <code bash> | ||
+ | read -r _ _ first middle last _ <<< | ||
+ | </ | ||
+ | |||
+ | |||
+ | <WRAP info> | ||
+ | **NOTE: | ||
+ | |||
+ | * It, and any other variable, can be used more than once in a single read command, if we don't care what goes into it. | ||
+ | |||
+ | * The first two fields are skipped. | ||
+ | * The next three fields are reading into variables. | ||
+ | * The final **_** will absorb any remaining fields on the line. | ||
+ | * It does not need to be repeated there. | ||
+ | |||
+ | <WRAP important> | ||
+ | **WARNING: | ||
+ | |||
+ | * Many other shells use **_** for other purposes that will at best cause this to not have the desired effect, and can break the script entirely. | ||
+ | * It is better to choose a unique variable that isn't used elsewhere in the script, even though **_** is a common Bash convention. | ||
+ | |||
+ | </ | ||
+ | |||
+ | </ | ||
+ | |||
+ | ---- | ||
+ | |||
bash/files/read_a_file/read_fields_from_a_file.1611667357.txt.gz · Last modified: 2021/01/26 13:22 by peter