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 [2011/11/18 05:51] ormaaj Simplify and bugfix I didn't notice because I use lastpipe. |
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> | ||
- | ===== Bugs ===== | + | 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. |
- | * 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. | + | <code> |
+ | #!/usr/bin/env bash | ||
+ | |||
+ | showRecord() { | ||
+ | printf 'key[%d] = %d, %d\n' "$1" "${vals[@]:keys[$1]*2:2}" | ||
+ | } | ||
+ | |||
+ | parseRecords() { | ||
+ | trap 'unset -f _f' RETURN | ||
+ | _f() { | ||
+ | local x | ||
+ | IFS=: read -r _ x | ||
+ | ((keys[x]=n++)) | ||
+ | } | ||
+ | local n | ||
+ | |||
+ | _f | ||
+ | mapfile -tc2 -C _f "$1" | ||
+ | eval "$1"'=("${'"$1"'[@]##*:}")' # Return the array with some modification | ||
+ | } | ||
+ | |||
+ | main() { | ||
+ | local -a keys vals | ||
+ | parseRecords vals | ||
+ | showRecord "$1" | ||
+ | } | ||
+ | |||
+ | main "$1" <<-"EOF" | ||
+ | fabric.domain:123 | ||
+ | routex:1 | ||
+ | routey:2 | ||
+ | fabric.domain:321 | ||
+ | routex:6 | ||
+ | routey:4 | ||
+ | EOF | ||
+ | </code> | ||
+ | |||
+ | 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 ===== | ||
+ | * 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). |