Differences
This shows you the differences between two versions of the page.
Both sides previous revision Previous revision Next revision | Previous revision | ||
commands:builtin:mapfile [2012/03/08 08:47] ormaaj [The callback] read + mapfile combination. |
commands:builtin:mapfile [2013/08/19 08:09] (current) ormaaj [Bugs] |
||
---|---|---|---|
Line 1: | Line 1: | ||
====== The mapfile builtin command ====== | ====== The mapfile builtin command ====== | ||
- | :V4: | ||
===== Synopsis ===== | ===== Synopsis ===== | ||
Line 89: | Line 88: | ||
</code> | </code> | ||
- | This example based upon yet another #bash question illustrates mapfile in combination with read. The sample input is the heredoc to ''main''. The goal is to build a "struct" based upon records in the input file made up from the numbers following the colon on each line. Every 3rd line is a key followed by 2 corresponding fields. The showRecord function takes a key and returns the record. | + | This example based on yet another #bash question illustrates mapfile in combination with read. The sample input is the heredoc to ''main''. The goal is to build a "struct" based upon records in the input file made up of the numbers following the colon on each line. Every 3rd line is a key followed by 2 corresponding fields. The showRecord function takes a key and returns the record. |
- | <code>#!/usr/bin/env bash | + | |
+ | <code> | ||
+ | #!/usr/bin/env bash | ||
showRecord() { | showRecord() { | ||
Line 97: | Line 98: | ||
parseRecords() { | parseRecords() { | ||
+ | trap 'unset -f _f' RETURN | ||
_f() { | _f() { | ||
local x | local x | ||
IFS=: read -r _ x | IFS=: read -r _ x | ||
- | keys[x]=n++ | + | ((keys[x]=n++)) |
} | } | ||
- | + | local n | |
- | trap 'unset -f _f' RETURN | + | |
- | local -i n | + | |
_f | _f | ||
- | mapfile -tc2 -C _f vals | + | mapfile -tc2 -C _f "$1" |
- | vals=("${vals[@]##*:}") | + | eval "$1"'=("${'"$1"'[@]##*:}")' # Return the array with some modification |
} | } | ||
main() { | main() { | ||
- | local -ai keys | + | local -a keys vals |
- | parseRecords | + | parseRecords vals |
showRecord "$1" | showRecord "$1" | ||
} | } | ||
- | main "$@" <<-"EOF" | + | main "$1" <<-"EOF" |
fabric.domain:123 | fabric.domain:123 | ||
routex:1 | routex:1 | ||
Line 124: | Line 124: | ||
routex:6 | routex:6 | ||
routey:4 | routey:4 | ||
- | EOF</code> | + | EOF |
+ | </code> | ||
- | For example, running "scriptname 321" would output "key[321] = 6, 4". Every 2 lines mapfile reads, the function _f is called which reads one line. Since the first line in the file is a key, and _f is responsible for the keys, it gets called once before mapfile so that mapfile starts reading the second line of input, calling _f with each subsequent 2 iterations. The RETURN trap is nothing to worry about, its just how I implement "private methods" in Bash. | + | For example, running ''scriptname 321'' would output ''key[321] = 6, 4''. Every 2 lines read by ''mapfile'', the function ''_f'' is called, which reads one additional line. Since the first line in the file is a key, and ''_f'' is responsible for the keys, it gets called first so that ''mapfile'' starts by reading the second line of input, calling ''_f'' with each subsequent 2 iterations. The RETURN trap is unimportant. |
===== Bugs ===== | ===== Bugs ===== | ||
- | * Early implementations were buggy. For example, ''mapfile'' filling the readline history buffer with calls to the ''CALLBACK''. This was fixed in 4.1 beta. Some bugs may still exist. | + | * Early implementations were buggy. For example, ''mapfile'' filling the readline history buffer with calls to the ''CALLBACK''. This was fixed in 4.1 beta. |
+ | * ''mapfile -n'' reads an extra line beyond the last line assigned to the array, through Bash. [[ftp://ftp.gnu.org/gnu/bash/bash-4.2-patches/bash42-035 | Fixed in 4.2.35]]. | ||
+ | * ''mapfile'' callbacks could cause a crash if the variable being assigned is manipulated in certain ways. [[https://lists.gnu.org/archive/html/bug-bash/2013-01/msg00039.html]]. Fixed in 4.3. | ||
===== To Do ===== | ===== To Do ===== | ||
* Create an implementation as a shell function that's portable between Ksh, Zsh, and Bash (and possibly other bourne-like shells with array support). | * Create an implementation as a shell function that's portable between Ksh, Zsh, and Bash (and possibly other bourne-like shells with array support). |