[{"data":1,"prerenderedAt":4960},["ShallowReactive",2],{"page-\u002Fbash\u002F09-arrays":3},{"id":4,"title":5,"body":6,"description":4953,"extension":4954,"meta":4955,"navigation":73,"path":4956,"seo":4957,"stem":4958,"__hash__":4959},"content\u002Fbash\u002F09-arrays.md","Bash 09 — Array Internals, Associative Maps & Data Structure Patterns",{"type":7,"value":8,"toc":4937},"minimark",[9,14,19,429,440,847,851,1067,1071,1426,1430,1835,1846,2215,2219,2691,2695,3083,3087,3509,3513,4261,4265,4795,4799,4803,4886,4933],[10,11,13],"h1",{"id":12},"_09-array-internals-associative-maps-data-structure-patterns","09 — Array Internals, Associative Maps & Data Structure Patterns",[15,16,18],"h2",{"id":17},"indexed-arrays-internal-representation","Indexed Arrays: Internal Representation",[20,21,23],"code-wrapper",{"language":22},"bash",[24,25,29],"pre",{"className":26,"code":27,"language":22,"meta":28,"style":28},"language-bash shiki shiki-themes github-light github-dark","# ── Indexed arrays store elements at integer indices (0-based, sparse) ──\nfruits=(\"apple\" \"banana\" \"cherry\")\n\n# ── Access ──\necho \"${fruits[0]}\"           # apple — first element\necho \"${fruits[1]}\"           # banana — second element\necho \"${fruits[-1]}\"          # cherry — last element (Bash 4.3+)\necho \"${fruits[@]}\"           # apple banana cherry — ALL elements, separate words\necho \"${fruits[*]}\"           # apple banana cherry — ALL elements, ONE string (IFS-joined)\necho \"${#fruits[@]}\"          # 3 — count of elements\necho \"${#fruits[0]}\"          # 5 — length of first element (\"apple\")\n\n# ── Modify ──\nfruits[1]=\"blueberry\"        # replace element at index 1\nfruits[10]=\"date\"            # sparse array! indices 4-9 are empty (unset)\necho \"${#fruits[@]}\"          # 4 — count doesn't include gaps\necho \"${!fruits[@]}\"          # 0 1 2 10 — INDICES (not values)\n\n# ── Append ──\nfruits+=(\"elderberry\")       # append at next available index (11, not 3 — sparse)\nfruits+=(\"fig\" \"grape\")      # append multiple\n\n# ── Delete ──\nunset 'fruits[0]'            # remove element at index 0 (leaves a gap)\necho \"${fruits[@]}\"          # blueberry cherry date elderberry fig grape\necho \"${#fruits[@]}\"          # 6 — count excludes the gap\necho \"${!fruits[@]}\"          # 1 2 10 11 12 13 — indices have gaps!\nunset 'fruits[*]'            # remove ALL elements (or: fruits=())\n","",[30,31,32,41,68,75,81,99,114,129,150,169,190,206,211,217,231,245,265,286,291,297,316,337,342,348,360,378,398,418],"code",{"__ignoreMap":28},[33,34,37],"span",{"class":35,"line":36},"line",1,[33,38,40],{"class":39},"sdCPZ","# ── Indexed arrays store elements at integer indices (0-based, sparse) ──\n",[33,42,44,48,52,55,59,62,65],{"class":35,"line":43},2,[33,45,47],{"class":46},"ssxIu","fruits",[33,49,51],{"class":50},"svdQ7","=",[33,53,54],{"class":46},"(",[33,56,58],{"class":57},"sJ6F3","\"apple\"",[33,60,61],{"class":57}," \"banana\"",[33,63,64],{"class":57}," \"cherry\"",[33,66,67],{"class":46},")\n",[33,69,71],{"class":35,"line":70},3,[33,72,74],{"emptyLinePlaceholder":73},true,"\n",[33,76,78],{"class":35,"line":77},4,[33,79,80],{"class":39},"# ── Access ──\n",[33,82,84,88,91,93,96],{"class":35,"line":83},5,[33,85,87],{"class":86},"snvgF","echo",[33,89,90],{"class":57}," \"${",[33,92,47],{"class":46},[33,94,95],{"class":57},"[0]}\"",[33,97,98],{"class":39},"           # apple — first element\n",[33,100,102,104,106,108,111],{"class":35,"line":101},6,[33,103,87],{"class":86},[33,105,90],{"class":57},[33,107,47],{"class":46},[33,109,110],{"class":57},"[1]}\"",[33,112,113],{"class":39},"           # banana — second element\n",[33,115,117,119,121,123,126],{"class":35,"line":116},7,[33,118,87],{"class":86},[33,120,90],{"class":57},[33,122,47],{"class":46},[33,124,125],{"class":57},"[-1]}\"",[33,127,128],{"class":39},"          # cherry — last element (Bash 4.3+)\n",[33,130,132,134,136,138,141,144,147],{"class":35,"line":131},8,[33,133,87],{"class":86},[33,135,90],{"class":57},[33,137,47],{"class":46},[33,139,140],{"class":57},"[",[33,142,143],{"class":50},"@",[33,145,146],{"class":57},"]}\"",[33,148,149],{"class":39},"           # apple banana cherry — ALL elements, separate words\n",[33,151,153,155,157,159,161,164,166],{"class":35,"line":152},9,[33,154,87],{"class":86},[33,156,90],{"class":57},[33,158,47],{"class":46},[33,160,140],{"class":57},[33,162,163],{"class":50},"*",[33,165,146],{"class":57},[33,167,168],{"class":39},"           # apple banana cherry — ALL elements, ONE string (IFS-joined)\n",[33,170,172,174,176,179,181,183,185,187],{"class":35,"line":171},10,[33,173,87],{"class":86},[33,175,90],{"class":57},[33,177,178],{"class":50},"#",[33,180,47],{"class":46},[33,182,140],{"class":57},[33,184,143],{"class":50},[33,186,146],{"class":57},[33,188,189],{"class":39},"          # 3 — count of elements\n",[33,191,193,195,197,199,201,203],{"class":35,"line":192},11,[33,194,87],{"class":86},[33,196,90],{"class":57},[33,198,178],{"class":50},[33,200,47],{"class":46},[33,202,95],{"class":57},[33,204,205],{"class":39},"          # 5 — length of first element (\"apple\")\n",[33,207,209],{"class":35,"line":208},12,[33,210,74],{"emptyLinePlaceholder":73},[33,212,214],{"class":35,"line":213},13,[33,215,216],{"class":39},"# ── Modify ──\n",[33,218,220,223,225,228],{"class":35,"line":219},14,[33,221,222],{"class":46},"fruits[1]",[33,224,51],{"class":50},[33,226,227],{"class":57},"\"blueberry\"",[33,229,230],{"class":39},"        # replace element at index 1\n",[33,232,234,237,239,242],{"class":35,"line":233},15,[33,235,236],{"class":46},"fruits[10]",[33,238,51],{"class":50},[33,240,241],{"class":57},"\"date\"",[33,243,244],{"class":39},"            # sparse array! indices 4-9 are empty (unset)\n",[33,246,248,250,252,254,256,258,260,262],{"class":35,"line":247},16,[33,249,87],{"class":86},[33,251,90],{"class":57},[33,253,178],{"class":50},[33,255,47],{"class":46},[33,257,140],{"class":57},[33,259,143],{"class":50},[33,261,146],{"class":57},[33,263,264],{"class":39},"          # 4 — count doesn't include gaps\n",[33,266,268,270,272,275,277,279,281,283],{"class":35,"line":267},17,[33,269,87],{"class":86},[33,271,90],{"class":57},[33,273,274],{"class":50},"!",[33,276,47],{"class":46},[33,278,140],{"class":57},[33,280,143],{"class":50},[33,282,146],{"class":57},[33,284,285],{"class":39},"          # 0 1 2 10 — INDICES (not values)\n",[33,287,289],{"class":35,"line":288},18,[33,290,74],{"emptyLinePlaceholder":73},[33,292,294],{"class":35,"line":293},19,[33,295,296],{"class":39},"# ── Append ──\n",[33,298,300,302,305,307,310,313],{"class":35,"line":299},20,[33,301,47],{"class":46},[33,303,304],{"class":50},"+=",[33,306,54],{"class":46},[33,308,309],{"class":57},"\"elderberry\"",[33,311,312],{"class":46},")       ",[33,314,315],{"class":39},"# append at next available index (11, not 3 — sparse)\n",[33,317,319,321,323,325,328,331,334],{"class":35,"line":318},21,[33,320,47],{"class":46},[33,322,304],{"class":50},[33,324,54],{"class":46},[33,326,327],{"class":57},"\"fig\"",[33,329,330],{"class":57}," \"grape\"",[33,332,333],{"class":46},")      ",[33,335,336],{"class":39},"# append multiple\n",[33,338,340],{"class":35,"line":339},22,[33,341,74],{"emptyLinePlaceholder":73},[33,343,345],{"class":35,"line":344},23,[33,346,347],{"class":39},"# ── Delete ──\n",[33,349,351,354,357],{"class":35,"line":350},24,[33,352,353],{"class":86},"unset",[33,355,356],{"class":57}," 'fruits[0]'",[33,358,359],{"class":39},"            # remove element at index 0 (leaves a gap)\n",[33,361,363,365,367,369,371,373,375],{"class":35,"line":362},25,[33,364,87],{"class":86},[33,366,90],{"class":57},[33,368,47],{"class":46},[33,370,140],{"class":57},[33,372,143],{"class":50},[33,374,146],{"class":57},[33,376,377],{"class":39},"          # blueberry cherry date elderberry fig grape\n",[33,379,381,383,385,387,389,391,393,395],{"class":35,"line":380},26,[33,382,87],{"class":86},[33,384,90],{"class":57},[33,386,178],{"class":50},[33,388,47],{"class":46},[33,390,140],{"class":57},[33,392,143],{"class":50},[33,394,146],{"class":57},[33,396,397],{"class":39},"          # 6 — count excludes the gap\n",[33,399,401,403,405,407,409,411,413,415],{"class":35,"line":400},27,[33,402,87],{"class":86},[33,404,90],{"class":57},[33,406,274],{"class":50},[33,408,47],{"class":46},[33,410,140],{"class":57},[33,412,143],{"class":50},[33,414,146],{"class":57},[33,416,417],{"class":39},"          # 1 2 10 11 12 13 — indices have gaps!\n",[33,419,421,423,426],{"class":35,"line":420},28,[33,422,353],{"class":86},[33,424,425],{"class":57}," 'fruits[*]'",[33,427,428],{"class":39},"            # remove ALL elements (or: fruits=())\n",[15,430,432,435,436,439],{"id":431},"vs-the-definitive-semantics",[30,433,434],{},"[@]"," vs ",[30,437,438],{},"[*]",": The Definitive Semantics",[20,441,442],{"language":22},[24,443,445],{"className":26,"code":444,"language":22,"meta":28,"style":28},"# ── \"${arr[@]}\" — each element is a separate, quoted word ──\n# ── \"${arr[*]}\" — all elements joined by IFS into ONE string ──\n\narr=(\"a\" \"b c\" \"d\")   # note: \"b c\" is one element with a space\n\n# ── Quoted @ (the ONLY correct way for iteration) ──\nfor x in \"${arr[@]}\"; do echo \"[$x]\"; done\n# [a]\n# [b c]    ← preserved as one word\n# [d]\n\n# ── Quoted * (joins into one string) ──\nfor x in \"${arr[*]}\"; do echo \"[$x]\"; done\n# [a b c d]  ← ONE iteration with all joined by IFS (space)\n\n# ── Unquoted @ (word-splits each element on IFS) ──\nfor x in ${arr[@]}; do echo \"[$x]\"; done\n# [a]\n# [b]       ← \"b c\" was split!\n# [c]\n# [d]\n\n# ── Unquoted * (same as unquoted @ — word-splits everything) ──\nfor x in ${arr[*]}; do echo \"[$x]\"; done\n# [a] [b] [c] [d]  ← same as unquoted @\n\n# ── Changing IFS affects [*] but NOT [@] ──\nsave=$IFS\nIFS=':'\necho \"${arr[*]}\"    # a:b c:d — joined by IFS (colon)\necho \"${arr[@]}\"    # a b c d — unaffected by IFS\nIFS=$save\n\n# ── Counting args with @ vs * ──\ncount_args() { echo \"$#\"; }\ncount_args \"${arr[@]}\"   # 3 — three separate args\ncount_args \"${arr[*]}\"   # 1 — one joined string\n",[30,446,447,452,457,461,485,489,494,538,543,548,553,557,562,596,601,605,610,640,644,649,654,658,662,667,695,700,704,709,719,730,748,766,776,781,787,811,829],{"__ignoreMap":28},[33,448,449],{"class":35,"line":36},[33,450,451],{"class":39},"# ── \"${arr[@]}\" — each element is a separate, quoted word ──\n",[33,453,454],{"class":35,"line":43},[33,455,456],{"class":39},"# ── \"${arr[*]}\" — all elements joined by IFS into ONE string ──\n",[33,458,459],{"class":35,"line":70},[33,460,74],{"emptyLinePlaceholder":73},[33,462,463,466,468,470,473,476,479,482],{"class":35,"line":77},[33,464,465],{"class":46},"arr",[33,467,51],{"class":50},[33,469,54],{"class":46},[33,471,472],{"class":57},"\"a\"",[33,474,475],{"class":57}," \"b c\"",[33,477,478],{"class":57}," \"d\"",[33,480,481],{"class":46},")   ",[33,483,484],{"class":39},"# note: \"b c\" is one element with a space\n",[33,486,487],{"class":35,"line":83},[33,488,74],{"emptyLinePlaceholder":73},[33,490,491],{"class":35,"line":101},[33,492,493],{"class":39},"# ── Quoted @ (the ONLY correct way for iteration) ──\n",[33,495,496,499,502,505,507,509,511,513,515,518,521,524,527,530,533,535],{"class":35,"line":116},[33,497,498],{"class":50},"for",[33,500,501],{"class":46}," x ",[33,503,504],{"class":50},"in",[33,506,90],{"class":57},[33,508,465],{"class":46},[33,510,140],{"class":57},[33,512,143],{"class":50},[33,514,146],{"class":57},[33,516,517],{"class":46},"; ",[33,519,520],{"class":50},"do",[33,522,523],{"class":86}," echo",[33,525,526],{"class":57}," \"[",[33,528,529],{"class":46},"$x",[33,531,532],{"class":57},"]\"",[33,534,517],{"class":46},[33,536,537],{"class":50},"done\n",[33,539,540],{"class":35,"line":131},[33,541,542],{"class":39},"# [a]\n",[33,544,545],{"class":35,"line":152},[33,546,547],{"class":39},"# [b c]    ← preserved as one word\n",[33,549,550],{"class":35,"line":171},[33,551,552],{"class":39},"# [d]\n",[33,554,555],{"class":35,"line":192},[33,556,74],{"emptyLinePlaceholder":73},[33,558,559],{"class":35,"line":208},[33,560,561],{"class":39},"# ── Quoted * (joins into one string) ──\n",[33,563,564,566,568,570,572,574,576,578,580,582,584,586,588,590,592,594],{"class":35,"line":213},[33,565,498],{"class":50},[33,567,501],{"class":46},[33,569,504],{"class":50},[33,571,90],{"class":57},[33,573,465],{"class":46},[33,575,140],{"class":57},[33,577,163],{"class":50},[33,579,146],{"class":57},[33,581,517],{"class":46},[33,583,520],{"class":50},[33,585,523],{"class":86},[33,587,526],{"class":57},[33,589,529],{"class":46},[33,591,532],{"class":57},[33,593,517],{"class":46},[33,595,537],{"class":50},[33,597,598],{"class":35,"line":219},[33,599,600],{"class":39},"# [a b c d]  ← ONE iteration with all joined by IFS (space)\n",[33,602,603],{"class":35,"line":233},[33,604,74],{"emptyLinePlaceholder":73},[33,606,607],{"class":35,"line":247},[33,608,609],{"class":39},"# ── Unquoted @ (word-splits each element on IFS) ──\n",[33,611,612,614,616,618,621,623,626,628,630,632,634,636,638],{"class":35,"line":267},[33,613,498],{"class":50},[33,615,501],{"class":46},[33,617,504],{"class":50},[33,619,620],{"class":46}," ${arr[",[33,622,143],{"class":50},[33,624,625],{"class":46},"]}; ",[33,627,520],{"class":50},[33,629,523],{"class":86},[33,631,526],{"class":57},[33,633,529],{"class":46},[33,635,532],{"class":57},[33,637,517],{"class":46},[33,639,537],{"class":50},[33,641,642],{"class":35,"line":288},[33,643,542],{"class":39},[33,645,646],{"class":35,"line":293},[33,647,648],{"class":39},"# [b]       ← \"b c\" was split!\n",[33,650,651],{"class":35,"line":299},[33,652,653],{"class":39},"# [c]\n",[33,655,656],{"class":35,"line":318},[33,657,552],{"class":39},[33,659,660],{"class":35,"line":339},[33,661,74],{"emptyLinePlaceholder":73},[33,663,664],{"class":35,"line":344},[33,665,666],{"class":39},"# ── Unquoted * (same as unquoted @ — word-splits everything) ──\n",[33,668,669,671,673,675,677,679,681,683,685,687,689,691,693],{"class":35,"line":350},[33,670,498],{"class":50},[33,672,501],{"class":46},[33,674,504],{"class":50},[33,676,620],{"class":46},[33,678,163],{"class":50},[33,680,625],{"class":46},[33,682,520],{"class":50},[33,684,523],{"class":86},[33,686,526],{"class":57},[33,688,529],{"class":46},[33,690,532],{"class":57},[33,692,517],{"class":46},[33,694,537],{"class":50},[33,696,697],{"class":35,"line":362},[33,698,699],{"class":39},"# [a] [b] [c] [d]  ← same as unquoted @\n",[33,701,702],{"class":35,"line":380},[33,703,74],{"emptyLinePlaceholder":73},[33,705,706],{"class":35,"line":400},[33,707,708],{"class":39},"# ── Changing IFS affects [*] but NOT [@] ──\n",[33,710,711,714,716],{"class":35,"line":420},[33,712,713],{"class":46},"save",[33,715,51],{"class":50},[33,717,718],{"class":46},"$IFS\n",[33,720,722,725,727],{"class":35,"line":721},29,[33,723,724],{"class":46},"IFS",[33,726,51],{"class":50},[33,728,729],{"class":57},"':'\n",[33,731,733,735,737,739,741,743,745],{"class":35,"line":732},30,[33,734,87],{"class":86},[33,736,90],{"class":57},[33,738,465],{"class":46},[33,740,140],{"class":57},[33,742,163],{"class":50},[33,744,146],{"class":57},[33,746,747],{"class":39},"    # a:b c:d — joined by IFS (colon)\n",[33,749,751,753,755,757,759,761,763],{"class":35,"line":750},31,[33,752,87],{"class":86},[33,754,90],{"class":57},[33,756,465],{"class":46},[33,758,140],{"class":57},[33,760,143],{"class":50},[33,762,146],{"class":57},[33,764,765],{"class":39},"    # a b c d — unaffected by IFS\n",[33,767,769,771,773],{"class":35,"line":768},32,[33,770,724],{"class":46},[33,772,51],{"class":50},[33,774,775],{"class":46},"$save\n",[33,777,779],{"class":35,"line":778},33,[33,780,74],{"emptyLinePlaceholder":73},[33,782,784],{"class":35,"line":783},34,[33,785,786],{"class":39},"# ── Counting args with @ vs * ──\n",[33,788,790,794,797,799,802,805,808],{"class":35,"line":789},35,[33,791,793],{"class":792},"sIsaT","count_args",[33,795,796],{"class":46},"() { ",[33,798,87],{"class":86},[33,800,801],{"class":57}," \"",[33,803,804],{"class":86},"$#",[33,806,807],{"class":57},"\"",[33,809,810],{"class":46},"; }\n",[33,812,814,816,818,820,822,824,826],{"class":35,"line":813},36,[33,815,793],{"class":792},[33,817,90],{"class":57},[33,819,465],{"class":46},[33,821,140],{"class":57},[33,823,143],{"class":50},[33,825,146],{"class":57},[33,827,828],{"class":39},"   # 3 — three separate args\n",[33,830,832,834,836,838,840,842,844],{"class":35,"line":831},37,[33,833,793],{"class":792},[33,835,90],{"class":57},[33,837,465],{"class":46},[33,839,140],{"class":57},[33,841,163],{"class":50},[33,843,146],{"class":57},[33,845,846],{"class":39},"   # 1 — one joined string\n",[15,848,850],{"id":849},"anti-pattern-iterating-without-quotes","Anti-Pattern: Iterating Without Quotes",[20,852,853],{"language":22},[24,854,856],{"className":26,"code":855,"language":22,"meta":28,"style":28},"# ❌ NAIVE — unquoted array iteration\nfiles=(\"my file.txt\" \"other file.txt\" \"third.txt\")\nfor file in $files; do       # $files (no [@]) expands to first element only!\n    echo \"$file\"\ndone\n# Only \"my file.txt\" (first element) is used, and it word-splits:\n# [my]\n# [file.txt]\n\n# ❌ ALSO WRONG — unquoted [@]\nfor file in ${files[@]}; do  # word-splits each element on spaces!\n    echo \"$file\"\ndone\n# [my] [file.txt] [other] [file.txt] [third.txt]\n\n# ✅ CORRECT — quoted [@]\nfor file in \"${files[@]}\"; do  # each element preserved as a separate word\n    echo \"$file\"\ndone\n# [my file.txt]\n# [other file.txt]\n# [third.txt]\n\n# ── Why $files (without [@]) is wrong ──\n# $files is shorthand for ${files[0]} — only the FIRST element.\n# It's a legacy POSIX sh compatibility feature (POSIX has no arrays, so $arr is the first element).\n# ALWAYS use \"${arr[@]}\" for all elements.\n",[30,857,858,863,883,900,913,917,922,927,932,936,941,961,971,975,980,984,989,1014,1024,1028,1033,1038,1043,1047,1052,1057,1062],{"__ignoreMap":28},[33,859,860],{"class":35,"line":36},[33,861,862],{"class":39},"# ❌ NAIVE — unquoted array iteration\n",[33,864,865,868,870,872,875,878,881],{"class":35,"line":43},[33,866,867],{"class":46},"files",[33,869,51],{"class":50},[33,871,54],{"class":46},[33,873,874],{"class":57},"\"my file.txt\"",[33,876,877],{"class":57}," \"other file.txt\"",[33,879,880],{"class":57}," \"third.txt\"",[33,882,67],{"class":46},[33,884,885,887,890,892,895,897],{"class":35,"line":70},[33,886,498],{"class":50},[33,888,889],{"class":46}," file ",[33,891,504],{"class":50},[33,893,894],{"class":46}," $files; ",[33,896,520],{"class":50},[33,898,899],{"class":39},"       # $files (no [@]) expands to first element only!\n",[33,901,902,905,907,910],{"class":35,"line":77},[33,903,904],{"class":86},"    echo",[33,906,801],{"class":57},[33,908,909],{"class":46},"$file",[33,911,912],{"class":57},"\"\n",[33,914,915],{"class":35,"line":83},[33,916,537],{"class":50},[33,918,919],{"class":35,"line":101},[33,920,921],{"class":39},"# Only \"my file.txt\" (first element) is used, and it word-splits:\n",[33,923,924],{"class":35,"line":116},[33,925,926],{"class":39},"# [my]\n",[33,928,929],{"class":35,"line":131},[33,930,931],{"class":39},"# [file.txt]\n",[33,933,934],{"class":35,"line":152},[33,935,74],{"emptyLinePlaceholder":73},[33,937,938],{"class":35,"line":171},[33,939,940],{"class":39},"# ❌ ALSO WRONG — unquoted [@]\n",[33,942,943,945,947,949,952,954,956,958],{"class":35,"line":192},[33,944,498],{"class":50},[33,946,889],{"class":46},[33,948,504],{"class":50},[33,950,951],{"class":46}," ${files[",[33,953,143],{"class":50},[33,955,625],{"class":46},[33,957,520],{"class":50},[33,959,960],{"class":39},"  # word-splits each element on spaces!\n",[33,962,963,965,967,969],{"class":35,"line":208},[33,964,904],{"class":86},[33,966,801],{"class":57},[33,968,909],{"class":46},[33,970,912],{"class":57},[33,972,973],{"class":35,"line":213},[33,974,537],{"class":50},[33,976,977],{"class":35,"line":219},[33,978,979],{"class":39},"# [my] [file.txt] [other] [file.txt] [third.txt]\n",[33,981,982],{"class":35,"line":233},[33,983,74],{"emptyLinePlaceholder":73},[33,985,986],{"class":35,"line":247},[33,987,988],{"class":39},"# ✅ CORRECT — quoted [@]\n",[33,990,991,993,995,997,999,1001,1003,1005,1007,1009,1011],{"class":35,"line":267},[33,992,498],{"class":50},[33,994,889],{"class":46},[33,996,504],{"class":50},[33,998,90],{"class":57},[33,1000,867],{"class":46},[33,1002,140],{"class":57},[33,1004,143],{"class":50},[33,1006,146],{"class":57},[33,1008,517],{"class":46},[33,1010,520],{"class":50},[33,1012,1013],{"class":39},"  # each element preserved as a separate word\n",[33,1015,1016,1018,1020,1022],{"class":35,"line":288},[33,1017,904],{"class":86},[33,1019,801],{"class":57},[33,1021,909],{"class":46},[33,1023,912],{"class":57},[33,1025,1026],{"class":35,"line":293},[33,1027,537],{"class":50},[33,1029,1030],{"class":35,"line":299},[33,1031,1032],{"class":39},"# [my file.txt]\n",[33,1034,1035],{"class":35,"line":318},[33,1036,1037],{"class":39},"# [other file.txt]\n",[33,1039,1040],{"class":35,"line":339},[33,1041,1042],{"class":39},"# [third.txt]\n",[33,1044,1045],{"class":35,"line":344},[33,1046,74],{"emptyLinePlaceholder":73},[33,1048,1049],{"class":35,"line":350},[33,1050,1051],{"class":39},"# ── Why $files (without [@]) is wrong ──\n",[33,1053,1054],{"class":35,"line":362},[33,1055,1056],{"class":39},"# $files is shorthand for ${files[0]} — only the FIRST element.\n",[33,1058,1059],{"class":35,"line":380},[33,1060,1061],{"class":39},"# It's a legacy POSIX sh compatibility feature (POSIX has no arrays, so $arr is the first element).\n",[33,1063,1064],{"class":35,"line":400},[33,1065,1066],{"class":39},"# ALWAYS use \"${arr[@]}\" for all elements.\n",[15,1068,1070],{"id":1069},"associative-arrays-bash-4","Associative Arrays (Bash 4+)",[20,1072,1073],{"language":22},[24,1074,1076],{"className":26,"code":1075,"language":22,"meta":28,"style":28},"# ── declare -A: key-value map (Bash 4+, NOT available on macOS 3.2) ──\ndeclare -A config\n\n# ── Assignment ──\nconfig[host]=\"localhost\"\nconfig[port]=\"8080\"\nconfig[debug]=true\nconfig[\"log_level\"]=\"info\"   # quotes around key are optional (for non-special keys)\n\n# ── Access ──\necho \"${config[host]}\"        # localhost\necho \"${config[port]}\"        # 8080\necho \"${config[nonexistent]}\"  # (empty — not an error with set -u if you use :-)\n\n# ── Keys and values ──\necho \"${!config[@]}\"          # host port debug log_level — KEYS (order is undefined!)\necho \"${config[@]}\"           # localhost 8080 true info — VALUES\necho \"${#config[@]}\"          # 4 — count\n\n# ── Iterate (order is NOT guaranteed — hash map) ──\nfor key in \"${!config[@]}\"; do\n    echo \"$key = ${config[$key]}\"\ndone\n\n# ── Check if key exists (Bash 4.2+) ──\nif [[ -v config[host] ]]; then   # true if key exists (even if value is empty)\n    echo \"host is set\"\nfi\n# ⚠️ [[ -n \"${config[host]}\" ]] is false if value is \"\" — use -v for key existence\n\n# ── Delete a key ──\nunset 'config[debug]'   # quotes prevent glob expansion of the key\necho \"${#config[@]}\"    # 3\n\n# ── Delete all ──\nconfig=()   # or: unset config (but this unsets the variable, not just clears it)\n",[30,1077,1078,1083,1094,1098,1103,1113,1123,1133,1152,1156,1160,1175,1189,1203,1207,1212,1231,1248,1267,1271,1276,1302,1323,1327,1331,1336,1350,1357,1362,1367,1371,1376,1386,1405,1409,1414],{"__ignoreMap":28},[33,1079,1080],{"class":35,"line":36},[33,1081,1082],{"class":39},"# ── declare -A: key-value map (Bash 4+, NOT available on macOS 3.2) ──\n",[33,1084,1085,1088,1091],{"class":35,"line":43},[33,1086,1087],{"class":50},"declare",[33,1089,1090],{"class":86}," -A",[33,1092,1093],{"class":46}," config\n",[33,1095,1096],{"class":35,"line":70},[33,1097,74],{"emptyLinePlaceholder":73},[33,1099,1100],{"class":35,"line":77},[33,1101,1102],{"class":39},"# ── Assignment ──\n",[33,1104,1105,1108,1110],{"class":35,"line":83},[33,1106,1107],{"class":46},"config[host]",[33,1109,51],{"class":50},[33,1111,1112],{"class":57},"\"localhost\"\n",[33,1114,1115,1118,1120],{"class":35,"line":101},[33,1116,1117],{"class":46},"config[port]",[33,1119,51],{"class":50},[33,1121,1122],{"class":57},"\"8080\"\n",[33,1124,1125,1128,1130],{"class":35,"line":116},[33,1126,1127],{"class":46},"config[debug]",[33,1129,51],{"class":50},[33,1131,1132],{"class":57},"true\n",[33,1134,1135,1138,1141,1144,1146,1149],{"class":35,"line":131},[33,1136,1137],{"class":792},"config[",[33,1139,1140],{"class":792},"\"log_level\"",[33,1142,1143],{"class":792},"]",[33,1145,51],{"class":57},[33,1147,1148],{"class":792},"\"info\"",[33,1150,1151],{"class":39},"   # quotes around key are optional (for non-special keys)\n",[33,1153,1154],{"class":35,"line":152},[33,1155,74],{"emptyLinePlaceholder":73},[33,1157,1158],{"class":35,"line":171},[33,1159,80],{"class":39},[33,1161,1162,1164,1166,1169,1172],{"class":35,"line":192},[33,1163,87],{"class":86},[33,1165,90],{"class":57},[33,1167,1168],{"class":46},"config",[33,1170,1171],{"class":57},"[host]}\"",[33,1173,1174],{"class":39},"        # localhost\n",[33,1176,1177,1179,1181,1183,1186],{"class":35,"line":208},[33,1178,87],{"class":86},[33,1180,90],{"class":57},[33,1182,1168],{"class":46},[33,1184,1185],{"class":57},"[port]}\"",[33,1187,1188],{"class":39},"        # 8080\n",[33,1190,1191,1193,1195,1197,1200],{"class":35,"line":213},[33,1192,87],{"class":86},[33,1194,90],{"class":57},[33,1196,1168],{"class":46},[33,1198,1199],{"class":57},"[nonexistent]}\"",[33,1201,1202],{"class":39},"  # (empty — not an error with set -u if you use :-)\n",[33,1204,1205],{"class":35,"line":219},[33,1206,74],{"emptyLinePlaceholder":73},[33,1208,1209],{"class":35,"line":233},[33,1210,1211],{"class":39},"# ── Keys and values ──\n",[33,1213,1214,1216,1218,1220,1222,1224,1226,1228],{"class":35,"line":247},[33,1215,87],{"class":86},[33,1217,90],{"class":57},[33,1219,274],{"class":50},[33,1221,1168],{"class":46},[33,1223,140],{"class":57},[33,1225,143],{"class":50},[33,1227,146],{"class":57},[33,1229,1230],{"class":39},"          # host port debug log_level — KEYS (order is undefined!)\n",[33,1232,1233,1235,1237,1239,1241,1243,1245],{"class":35,"line":267},[33,1234,87],{"class":86},[33,1236,90],{"class":57},[33,1238,1168],{"class":46},[33,1240,140],{"class":57},[33,1242,143],{"class":50},[33,1244,146],{"class":57},[33,1246,1247],{"class":39},"           # localhost 8080 true info — VALUES\n",[33,1249,1250,1252,1254,1256,1258,1260,1262,1264],{"class":35,"line":288},[33,1251,87],{"class":86},[33,1253,90],{"class":57},[33,1255,178],{"class":50},[33,1257,1168],{"class":46},[33,1259,140],{"class":57},[33,1261,143],{"class":50},[33,1263,146],{"class":57},[33,1265,1266],{"class":39},"          # 4 — count\n",[33,1268,1269],{"class":35,"line":293},[33,1270,74],{"emptyLinePlaceholder":73},[33,1272,1273],{"class":35,"line":299},[33,1274,1275],{"class":39},"# ── Iterate (order is NOT guaranteed — hash map) ──\n",[33,1277,1278,1280,1283,1285,1287,1289,1291,1293,1295,1297,1299],{"class":35,"line":318},[33,1279,498],{"class":50},[33,1281,1282],{"class":46}," key ",[33,1284,504],{"class":50},[33,1286,90],{"class":57},[33,1288,274],{"class":50},[33,1290,1168],{"class":46},[33,1292,140],{"class":57},[33,1294,143],{"class":50},[33,1296,146],{"class":57},[33,1298,517],{"class":46},[33,1300,1301],{"class":50},"do\n",[33,1303,1304,1306,1308,1311,1314,1316,1318,1320],{"class":35,"line":339},[33,1305,904],{"class":86},[33,1307,801],{"class":57},[33,1309,1310],{"class":46},"$key",[33,1312,1313],{"class":57}," = ${",[33,1315,1168],{"class":46},[33,1317,140],{"class":57},[33,1319,1310],{"class":46},[33,1321,1322],{"class":57},"]}\"\n",[33,1324,1325],{"class":35,"line":344},[33,1326,537],{"class":50},[33,1328,1329],{"class":35,"line":350},[33,1330,74],{"emptyLinePlaceholder":73},[33,1332,1333],{"class":35,"line":362},[33,1334,1335],{"class":39},"# ── Check if key exists (Bash 4.2+) ──\n",[33,1337,1338,1341,1344,1347],{"class":35,"line":380},[33,1339,1340],{"class":50},"if",[33,1342,1343],{"class":46}," [[ -v config[host] ]]; ",[33,1345,1346],{"class":50},"then",[33,1348,1349],{"class":39},"   # true if key exists (even if value is empty)\n",[33,1351,1352,1354],{"class":35,"line":400},[33,1353,904],{"class":86},[33,1355,1356],{"class":57}," \"host is set\"\n",[33,1358,1359],{"class":35,"line":420},[33,1360,1361],{"class":50},"fi\n",[33,1363,1364],{"class":35,"line":721},[33,1365,1366],{"class":39},"# ⚠️ [[ -n \"${config[host]}\" ]] is false if value is \"\" — use -v for key existence\n",[33,1368,1369],{"class":35,"line":732},[33,1370,74],{"emptyLinePlaceholder":73},[33,1372,1373],{"class":35,"line":750},[33,1374,1375],{"class":39},"# ── Delete a key ──\n",[33,1377,1378,1380,1383],{"class":35,"line":768},[33,1379,353],{"class":86},[33,1381,1382],{"class":57}," 'config[debug]'",[33,1384,1385],{"class":39},"   # quotes prevent glob expansion of the key\n",[33,1387,1388,1390,1392,1394,1396,1398,1400,1402],{"class":35,"line":778},[33,1389,87],{"class":86},[33,1391,90],{"class":57},[33,1393,178],{"class":50},[33,1395,1168],{"class":46},[33,1397,140],{"class":57},[33,1399,143],{"class":50},[33,1401,146],{"class":57},[33,1403,1404],{"class":39},"    # 3\n",[33,1406,1407],{"class":35,"line":783},[33,1408,74],{"emptyLinePlaceholder":73},[33,1410,1411],{"class":35,"line":789},[33,1412,1413],{"class":39},"# ── Delete all ──\n",[33,1415,1416,1418,1420,1423],{"class":35,"line":813},[33,1417,1168],{"class":46},[33,1419,51],{"class":50},[33,1421,1422],{"class":46},"()   ",[33,1424,1425],{"class":39},"# or: unset config (but this unsets the variable, not just clears it)\n",[15,1427,1429],{"id":1428},"production-pattern-config-loader-with-defaults","Production Pattern: Config Loader with Defaults",[20,1431,1432],{"language":22},[24,1433,1435],{"className":26,"code":1434,"language":22,"meta":28,"style":28},"#!\u002Fusr\u002Fbin\u002Fenv bash\ndeclare -A config\n\nload_config() {\n    local config_file=\"$1\"\n    [[ -f \"$config_file\" ]] || die \"config not found: $config_file\"\n\n    while IFS='=' read -r key value; do\n        # Skip comments and blank lines\n        [[ -z \"$key\" || \"$key\" =~ ^[[:space:]]*# ]] && continue\n\n        # Strip whitespace around key and value\n        key=\"${key\u002F\u002F \u002F}\"\n        value=\"${value# }\"   # strip leading space\n        value=\"${value% }\"   # strip trailing space\n\n        config[\"$key\"]=\"$value\"\n    done \u003C \"$config_file\"\n}\n\n# ── Config file (config.env) ──\n# host=localhost\n# port=8080\n# debug=true\n\nload_config config.env\n\n# ── Access with defaults ──\nhost=\"${config[host]:-localhost}\"\nport=\"${config[port]:-8080}\"\ndebug=\"${config[debug]:-false}\"\n\necho \"host=$host port=$port debug=$debug\"\n",[30,1436,1437,1442,1450,1454,1462,1479,1510,1514,1543,1548,1585,1589,1594,1616,1636,1654,1658,1680,1694,1699,1703,1708,1713,1718,1723,1727,1734,1738,1743,1765,1786,1807,1811],{"__ignoreMap":28},[33,1438,1439],{"class":35,"line":36},[33,1440,1441],{"class":39},"#!\u002Fusr\u002Fbin\u002Fenv bash\n",[33,1443,1444,1446,1448],{"class":35,"line":43},[33,1445,1087],{"class":50},[33,1447,1090],{"class":86},[33,1449,1093],{"class":46},[33,1451,1452],{"class":35,"line":70},[33,1453,74],{"emptyLinePlaceholder":73},[33,1455,1456,1459],{"class":35,"line":77},[33,1457,1458],{"class":792},"load_config",[33,1460,1461],{"class":46},"() {\n",[33,1463,1464,1467,1470,1472,1474,1477],{"class":35,"line":83},[33,1465,1466],{"class":50},"    local",[33,1468,1469],{"class":46}," config_file",[33,1471,51],{"class":50},[33,1473,807],{"class":57},[33,1475,1476],{"class":86},"$1",[33,1478,912],{"class":57},[33,1480,1481,1484,1487,1489,1492,1494,1497,1500,1503,1506,1508],{"class":35,"line":101},[33,1482,1483],{"class":46},"    [[ ",[33,1485,1486],{"class":50},"-f",[33,1488,801],{"class":57},[33,1490,1491],{"class":46},"$config_file",[33,1493,807],{"class":57},[33,1495,1496],{"class":46}," ]] ",[33,1498,1499],{"class":50},"||",[33,1501,1502],{"class":792}," die",[33,1504,1505],{"class":57}," \"config not found: ",[33,1507,1491],{"class":46},[33,1509,912],{"class":57},[33,1511,1512],{"class":35,"line":116},[33,1513,74],{"emptyLinePlaceholder":73},[33,1515,1516,1519,1522,1524,1527,1530,1533,1536,1539,1541],{"class":35,"line":131},[33,1517,1518],{"class":50},"    while",[33,1520,1521],{"class":46}," IFS",[33,1523,51],{"class":50},[33,1525,1526],{"class":57},"'='",[33,1528,1529],{"class":86}," read",[33,1531,1532],{"class":86}," -r",[33,1534,1535],{"class":57}," key",[33,1537,1538],{"class":57}," value",[33,1540,517],{"class":46},[33,1542,1301],{"class":50},[33,1544,1545],{"class":35,"line":152},[33,1546,1547],{"class":39},"        # Skip comments and blank lines\n",[33,1549,1550,1553,1556,1558,1560,1562,1565,1567,1569,1571,1574,1577,1579,1582],{"class":35,"line":171},[33,1551,1552],{"class":46},"        [[ ",[33,1554,1555],{"class":50},"-z",[33,1557,801],{"class":57},[33,1559,1310],{"class":46},[33,1561,807],{"class":57},[33,1563,1564],{"class":50}," ||",[33,1566,801],{"class":57},[33,1568,1310],{"class":46},[33,1570,807],{"class":57},[33,1572,1573],{"class":50}," =~",[33,1575,1576],{"class":46}," ^[[:space:]]",[33,1578,163],{"class":50},[33,1580,1581],{"class":46},"# ]] && ",[33,1583,1584],{"class":50},"continue\n",[33,1586,1587],{"class":35,"line":192},[33,1588,74],{"emptyLinePlaceholder":73},[33,1590,1591],{"class":35,"line":208},[33,1592,1593],{"class":39},"        # Strip whitespace around key and value\n",[33,1595,1596,1599,1601,1604,1607,1610,1613],{"class":35,"line":213},[33,1597,1598],{"class":46},"        key",[33,1600,51],{"class":50},[33,1602,1603],{"class":57},"\"${",[33,1605,1606],{"class":46},"key",[33,1608,1609],{"class":50},"\u002F\u002F",[33,1611,1612],{"class":50}," \u002F",[33,1614,1615],{"class":57},"}\"\n",[33,1617,1618,1621,1623,1625,1628,1630,1633],{"class":35,"line":219},[33,1619,1620],{"class":46},"        value",[33,1622,51],{"class":50},[33,1624,1603],{"class":57},[33,1626,1627],{"class":46},"value",[33,1629,178],{"class":50},[33,1631,1632],{"class":57}," }\"",[33,1634,1635],{"class":39},"   # strip leading space\n",[33,1637,1638,1640,1642,1644,1646,1649,1651],{"class":35,"line":233},[33,1639,1620],{"class":46},[33,1641,51],{"class":50},[33,1643,1603],{"class":57},[33,1645,1627],{"class":46},[33,1647,1648],{"class":50},"%",[33,1650,1632],{"class":57},[33,1652,1653],{"class":39},"   # strip trailing space\n",[33,1655,1656],{"class":35,"line":247},[33,1657,74],{"emptyLinePlaceholder":73},[33,1659,1660,1663,1665,1667,1669,1671,1673,1675,1678],{"class":35,"line":267},[33,1661,1662],{"class":792},"        config[",[33,1664,807],{"class":792},[33,1666,1310],{"class":46},[33,1668,807],{"class":792},[33,1670,1143],{"class":792},[33,1672,51],{"class":57},[33,1674,807],{"class":792},[33,1676,1677],{"class":46},"$value",[33,1679,912],{"class":792},[33,1681,1682,1685,1688,1690,1692],{"class":35,"line":288},[33,1683,1684],{"class":50},"    done",[33,1686,1687],{"class":50}," \u003C",[33,1689,801],{"class":57},[33,1691,1491],{"class":46},[33,1693,912],{"class":57},[33,1695,1696],{"class":35,"line":293},[33,1697,1698],{"class":46},"}\n",[33,1700,1701],{"class":35,"line":299},[33,1702,74],{"emptyLinePlaceholder":73},[33,1704,1705],{"class":35,"line":318},[33,1706,1707],{"class":39},"# ── Config file (config.env) ──\n",[33,1709,1710],{"class":35,"line":339},[33,1711,1712],{"class":39},"# host=localhost\n",[33,1714,1715],{"class":35,"line":344},[33,1716,1717],{"class":39},"# port=8080\n",[33,1719,1720],{"class":35,"line":350},[33,1721,1722],{"class":39},"# debug=true\n",[33,1724,1725],{"class":35,"line":362},[33,1726,74],{"emptyLinePlaceholder":73},[33,1728,1729,1731],{"class":35,"line":380},[33,1730,1458],{"class":792},[33,1732,1733],{"class":57}," config.env\n",[33,1735,1736],{"class":35,"line":400},[33,1737,74],{"emptyLinePlaceholder":73},[33,1739,1740],{"class":35,"line":420},[33,1741,1742],{"class":39},"# ── Access with defaults ──\n",[33,1744,1745,1748,1750,1752,1754,1757,1760,1763],{"class":35,"line":721},[33,1746,1747],{"class":46},"host",[33,1749,51],{"class":50},[33,1751,1603],{"class":57},[33,1753,1168],{"class":46},[33,1755,1756],{"class":57},"[host]",[33,1758,1759],{"class":50},":-",[33,1761,1762],{"class":46},"localhost",[33,1764,1615],{"class":57},[33,1766,1767,1770,1772,1774,1776,1779,1781,1784],{"class":35,"line":732},[33,1768,1769],{"class":46},"port",[33,1771,51],{"class":50},[33,1773,1603],{"class":57},[33,1775,1168],{"class":46},[33,1777,1778],{"class":57},"[port]",[33,1780,1759],{"class":50},[33,1782,1783],{"class":46},"8080",[33,1785,1615],{"class":57},[33,1787,1788,1791,1793,1795,1797,1800,1802,1805],{"class":35,"line":750},[33,1789,1790],{"class":46},"debug",[33,1792,51],{"class":50},[33,1794,1603],{"class":57},[33,1796,1168],{"class":46},[33,1798,1799],{"class":57},"[debug]",[33,1801,1759],{"class":50},[33,1803,1804],{"class":46},"false",[33,1806,1615],{"class":57},[33,1808,1809],{"class":35,"line":768},[33,1810,74],{"emptyLinePlaceholder":73},[33,1812,1813,1815,1818,1821,1824,1827,1830,1833],{"class":35,"line":778},[33,1814,87],{"class":86},[33,1816,1817],{"class":57}," \"host=",[33,1819,1820],{"class":46},"$host",[33,1822,1823],{"class":57}," port=",[33,1825,1826],{"class":46},"$port",[33,1828,1829],{"class":57}," debug=",[33,1831,1832],{"class":46},"$debug",[33,1834,912],{"class":57},[15,1836,1838,1841,1842,1845],{"id":1837},"mapfile-readarray-bulk-read-into-arrays",[30,1839,1840],{},"mapfile"," \u002F ",[30,1843,1844],{},"readarray",": Bulk Read Into Arrays",[20,1847,1848],{"language":22},[24,1849,1851],{"className":26,"code":1850,"language":22,"meta":28,"style":28},"# ── mapfile (Bash 4+) reads lines from stdin into an array ──\n# readarray is an alias for mapfile\n\nmapfile -t lines \u003C \u002Fetc\u002Fpasswd\necho \"${#lines[@]}\"      # number of lines\necho \"${lines[0]}\"       # first line\necho \"${lines[-1]}\"      # last line\n\n# ── -t: strip trailing newline (almost always want this) ──\nmapfile -t lines \u003C file.txt   # without -t, each element includes \\n\n\n# ── From a command (process substitution — no subshell trap) ──\nmapfile -t py_files \u003C \u003C(find . -name \"*.py\" -print0 | xargs -0 -n1 echo)\n# Wait, this is wrong — -print0 is null-delimited, but mapfile is newline-delimited.\n# Correct:\nmapfile -t py_files \u003C \u003C(find . -name \"*.py\")\nfor f in \"${py_files[@]}\"; do\n    echo \"found: $f\"\ndone\n# ⚠️ This breaks on filenames with newlines. For safety, use -d '' with mapfile:\n\nmapfile -d '' -t py_files \u003C \u003C(find . -name \"*.py\" -print0)\n# -d '' sets the delimiter to null byte (matches -print0)\n# This is the ONLY safe way to read filenames into an array.\n\n# ── Skip lines: -s N (skip first N lines) ──\nmapfile -t -s 1 lines \u003C file.txt   # skip header (first line)\n\n# ── Limit: -n N (read at most N lines) ──\nmapfile -t -n 100 lines \u003C huge_file.txt   # read only first 100 lines\n\n# ── Read into a specific array name ──\nmapfile -t data \u003C input.csv\n# or: readarray -t data \u003C input.csv\n",[30,1852,1853,1858,1863,1867,1882,1902,1915,1928,1932,1937,1953,1957,1962,2006,2011,2016,2037,2061,2073,2077,2082,2086,2116,2121,2126,2130,2135,2156,2160,2165,2187,2191,2196,2210],{"__ignoreMap":28},[33,1854,1855],{"class":35,"line":36},[33,1856,1857],{"class":39},"# ── mapfile (Bash 4+) reads lines from stdin into an array ──\n",[33,1859,1860],{"class":35,"line":43},[33,1861,1862],{"class":39},"# readarray is an alias for mapfile\n",[33,1864,1865],{"class":35,"line":70},[33,1866,74],{"emptyLinePlaceholder":73},[33,1868,1869,1871,1874,1877,1879],{"class":35,"line":77},[33,1870,1840],{"class":792},[33,1872,1873],{"class":86}," -t",[33,1875,1876],{"class":57}," lines",[33,1878,1687],{"class":50},[33,1880,1881],{"class":57}," \u002Fetc\u002Fpasswd\n",[33,1883,1884,1886,1888,1890,1893,1895,1897,1899],{"class":35,"line":83},[33,1885,87],{"class":86},[33,1887,90],{"class":57},[33,1889,178],{"class":50},[33,1891,1892],{"class":46},"lines",[33,1894,140],{"class":57},[33,1896,143],{"class":50},[33,1898,146],{"class":57},[33,1900,1901],{"class":39},"      # number of lines\n",[33,1903,1904,1906,1908,1910,1912],{"class":35,"line":101},[33,1905,87],{"class":86},[33,1907,90],{"class":57},[33,1909,1892],{"class":46},[33,1911,95],{"class":57},[33,1913,1914],{"class":39},"       # first line\n",[33,1916,1917,1919,1921,1923,1925],{"class":35,"line":116},[33,1918,87],{"class":86},[33,1920,90],{"class":57},[33,1922,1892],{"class":46},[33,1924,125],{"class":57},[33,1926,1927],{"class":39},"      # last line\n",[33,1929,1930],{"class":35,"line":131},[33,1931,74],{"emptyLinePlaceholder":73},[33,1933,1934],{"class":35,"line":152},[33,1935,1936],{"class":39},"# ── -t: strip trailing newline (almost always want this) ──\n",[33,1938,1939,1941,1943,1945,1947,1950],{"class":35,"line":171},[33,1940,1840],{"class":792},[33,1942,1873],{"class":86},[33,1944,1876],{"class":57},[33,1946,1687],{"class":50},[33,1948,1949],{"class":57}," file.txt",[33,1951,1952],{"class":39},"   # without -t, each element includes \\n\n",[33,1954,1955],{"class":35,"line":192},[33,1956,74],{"emptyLinePlaceholder":73},[33,1958,1959],{"class":35,"line":208},[33,1960,1961],{"class":39},"# ── From a command (process substitution — no subshell trap) ──\n",[33,1963,1964,1966,1968,1971,1973,1976,1979,1982,1985,1988,1991,1994,1997,2000,2003],{"class":35,"line":213},[33,1965,1840],{"class":792},[33,1967,1873],{"class":86},[33,1969,1970],{"class":57}," py_files",[33,1972,1687],{"class":50},[33,1974,1975],{"class":57}," \u003C(",[33,1977,1978],{"class":792},"find",[33,1980,1981],{"class":57}," . ",[33,1983,1984],{"class":86},"-name",[33,1986,1987],{"class":57}," \"*.py\" ",[33,1989,1990],{"class":86},"-print0",[33,1992,1993],{"class":50}," |",[33,1995,1996],{"class":792}," xargs",[33,1998,1999],{"class":86}," -0",[33,2001,2002],{"class":86}," -n1",[33,2004,2005],{"class":57}," echo)\n",[33,2007,2008],{"class":35,"line":219},[33,2009,2010],{"class":39},"# Wait, this is wrong — -print0 is null-delimited, but mapfile is newline-delimited.\n",[33,2012,2013],{"class":35,"line":233},[33,2014,2015],{"class":39},"# Correct:\n",[33,2017,2018,2020,2022,2024,2026,2028,2030,2032,2034],{"class":35,"line":247},[33,2019,1840],{"class":792},[33,2021,1873],{"class":86},[33,2023,1970],{"class":57},[33,2025,1687],{"class":50},[33,2027,1975],{"class":57},[33,2029,1978],{"class":792},[33,2031,1981],{"class":57},[33,2033,1984],{"class":86},[33,2035,2036],{"class":57}," \"*.py\")\n",[33,2038,2039,2041,2044,2046,2048,2051,2053,2055,2057,2059],{"class":35,"line":267},[33,2040,498],{"class":50},[33,2042,2043],{"class":46}," f ",[33,2045,504],{"class":50},[33,2047,90],{"class":57},[33,2049,2050],{"class":46},"py_files",[33,2052,140],{"class":57},[33,2054,143],{"class":50},[33,2056,146],{"class":57},[33,2058,517],{"class":46},[33,2060,1301],{"class":50},[33,2062,2063,2065,2068,2071],{"class":35,"line":288},[33,2064,904],{"class":86},[33,2066,2067],{"class":57}," \"found: ",[33,2069,2070],{"class":46},"$f",[33,2072,912],{"class":57},[33,2074,2075],{"class":35,"line":293},[33,2076,537],{"class":50},[33,2078,2079],{"class":35,"line":299},[33,2080,2081],{"class":39},"# ⚠️ This breaks on filenames with newlines. For safety, use -d '' with mapfile:\n",[33,2083,2084],{"class":35,"line":318},[33,2085,74],{"emptyLinePlaceholder":73},[33,2087,2088,2090,2093,2096,2098,2100,2102,2104,2106,2108,2110,2112,2114],{"class":35,"line":339},[33,2089,1840],{"class":792},[33,2091,2092],{"class":86}," -d",[33,2094,2095],{"class":57}," ''",[33,2097,1873],{"class":86},[33,2099,1970],{"class":57},[33,2101,1687],{"class":50},[33,2103,1975],{"class":57},[33,2105,1978],{"class":792},[33,2107,1981],{"class":57},[33,2109,1984],{"class":86},[33,2111,1987],{"class":57},[33,2113,1990],{"class":86},[33,2115,67],{"class":57},[33,2117,2118],{"class":35,"line":344},[33,2119,2120],{"class":39},"# -d '' sets the delimiter to null byte (matches -print0)\n",[33,2122,2123],{"class":35,"line":350},[33,2124,2125],{"class":39},"# This is the ONLY safe way to read filenames into an array.\n",[33,2127,2128],{"class":35,"line":362},[33,2129,74],{"emptyLinePlaceholder":73},[33,2131,2132],{"class":35,"line":380},[33,2133,2134],{"class":39},"# ── Skip lines: -s N (skip first N lines) ──\n",[33,2136,2137,2139,2141,2144,2147,2149,2151,2153],{"class":35,"line":400},[33,2138,1840],{"class":792},[33,2140,1873],{"class":86},[33,2142,2143],{"class":86}," -s",[33,2145,2146],{"class":86}," 1",[33,2148,1876],{"class":57},[33,2150,1687],{"class":50},[33,2152,1949],{"class":57},[33,2154,2155],{"class":39},"   # skip header (first line)\n",[33,2157,2158],{"class":35,"line":420},[33,2159,74],{"emptyLinePlaceholder":73},[33,2161,2162],{"class":35,"line":721},[33,2163,2164],{"class":39},"# ── Limit: -n N (read at most N lines) ──\n",[33,2166,2167,2169,2171,2174,2177,2179,2181,2184],{"class":35,"line":732},[33,2168,1840],{"class":792},[33,2170,1873],{"class":86},[33,2172,2173],{"class":86}," -n",[33,2175,2176],{"class":86}," 100",[33,2178,1876],{"class":57},[33,2180,1687],{"class":50},[33,2182,2183],{"class":57}," huge_file.txt",[33,2185,2186],{"class":39},"   # read only first 100 lines\n",[33,2188,2189],{"class":35,"line":750},[33,2190,74],{"emptyLinePlaceholder":73},[33,2192,2193],{"class":35,"line":768},[33,2194,2195],{"class":39},"# ── Read into a specific array name ──\n",[33,2197,2198,2200,2202,2205,2207],{"class":35,"line":778},[33,2199,1840],{"class":792},[33,2201,1873],{"class":86},[33,2203,2204],{"class":57}," data",[33,2206,1687],{"class":50},[33,2208,2209],{"class":57}," input.csv\n",[33,2211,2212],{"class":35,"line":783},[33,2213,2214],{"class":39},"# or: readarray -t data \u003C input.csv\n",[15,2216,2218],{"id":2217},"string-array-conversion","String ↔ Array Conversion",[20,2220,2221],{"language":22},[24,2222,2224],{"className":26,"code":2223,"language":22,"meta":28,"style":28},"# ── String → array: split on delimiter ──\nstr=\"apple,banana,cherry\"\n\n# Method 1: IFS + read -ra (preferred — no subprocess)\nIFS=',' read -ra fruits \u003C\u003C\u003C \"$str\"\necho \"${fruits[0]}\"   # apple\necho \"${fruits[@]}\"   # apple banana cherry\n\n# Method 2: Parameter expansion + array (for simple cases)\n# (No direct split, but you can use () with a pre-split string)\n\n# ── ⚠️ IFS=',' read changes IFS ONLY for that read command ──\n# The global IFS is NOT affected (the IFS=, is a per-command prefix)\necho \"$IFS\"   # still \" \\t\\n\" (default) — not changed\n\n# ── Split on multiple delimiters ──\nstr=\"a,b;c:d\"\nIFS=',;:' read -ra parts \u003C\u003C\u003C \"$str\"\necho \"${parts[@]}\"   # a b c d — split on any of , ; :\n\n# ── Array → string: join ──\narr=(\"apple\" \"banana\" \"cherry\")\n\n# Method 1: default IFS join (space)\njoined=\"${arr[*]}\"\necho \"$joined\"   # apple banana cherry\n\n# Method 2: custom delimiter (temporary IFS change)\njoin_by() {\n    local delim=$1; shift\n    local first=$1; shift\n    local result=$first\n    local item\n    for item in \"$@\"; do\n        result+=\"$delim$item\"\n    done\n    printf '%s' \"$result\"\n}\njoin_by \", \" \"${arr[@]}\"   # apple, banana, cherry\n\n# Method 3: IFS trick (one-liner, but affects global IFS temporarily)\nsave=$IFS\nIFS=', '\njoined=\"${arr[*]}\"\nIFS=$save\necho \"$joined\"   # apple, banana, cherry (IFS=',' joins with comma)\n",[30,2225,2226,2231,2241,2245,2250,2277,2290,2307,2311,2316,2321,2325,2330,2335,2349,2353,2358,2367,2391,2409,2413,2418,2434,2438,2443,2460,2473,2477,2482,2489,2506,2521,2533,2540,2561,2575,2580,2595,2600,2621,2626,2632,2641,2651,2668,2677],{"__ignoreMap":28},[33,2227,2228],{"class":35,"line":36},[33,2229,2230],{"class":39},"# ── String → array: split on delimiter ──\n",[33,2232,2233,2236,2238],{"class":35,"line":43},[33,2234,2235],{"class":46},"str",[33,2237,51],{"class":50},[33,2239,2240],{"class":57},"\"apple,banana,cherry\"\n",[33,2242,2243],{"class":35,"line":70},[33,2244,74],{"emptyLinePlaceholder":73},[33,2246,2247],{"class":35,"line":77},[33,2248,2249],{"class":39},"# Method 1: IFS + read -ra (preferred — no subprocess)\n",[33,2251,2252,2254,2256,2259,2261,2264,2267,2270,2272,2275],{"class":35,"line":83},[33,2253,724],{"class":46},[33,2255,51],{"class":50},[33,2257,2258],{"class":57},"','",[33,2260,1529],{"class":86},[33,2262,2263],{"class":86}," -ra",[33,2265,2266],{"class":57}," fruits",[33,2268,2269],{"class":50}," \u003C\u003C\u003C",[33,2271,801],{"class":57},[33,2273,2274],{"class":46},"$str",[33,2276,912],{"class":57},[33,2278,2279,2281,2283,2285,2287],{"class":35,"line":101},[33,2280,87],{"class":86},[33,2282,90],{"class":57},[33,2284,47],{"class":46},[33,2286,95],{"class":57},[33,2288,2289],{"class":39},"   # apple\n",[33,2291,2292,2294,2296,2298,2300,2302,2304],{"class":35,"line":116},[33,2293,87],{"class":86},[33,2295,90],{"class":57},[33,2297,47],{"class":46},[33,2299,140],{"class":57},[33,2301,143],{"class":50},[33,2303,146],{"class":57},[33,2305,2306],{"class":39},"   # apple banana cherry\n",[33,2308,2309],{"class":35,"line":131},[33,2310,74],{"emptyLinePlaceholder":73},[33,2312,2313],{"class":35,"line":152},[33,2314,2315],{"class":39},"# Method 2: Parameter expansion + array (for simple cases)\n",[33,2317,2318],{"class":35,"line":171},[33,2319,2320],{"class":39},"# (No direct split, but you can use () with a pre-split string)\n",[33,2322,2323],{"class":35,"line":192},[33,2324,74],{"emptyLinePlaceholder":73},[33,2326,2327],{"class":35,"line":208},[33,2328,2329],{"class":39},"# ── ⚠️ IFS=',' read changes IFS ONLY for that read command ──\n",[33,2331,2332],{"class":35,"line":213},[33,2333,2334],{"class":39},"# The global IFS is NOT affected (the IFS=, is a per-command prefix)\n",[33,2336,2337,2339,2341,2344,2346],{"class":35,"line":219},[33,2338,87],{"class":86},[33,2340,801],{"class":57},[33,2342,2343],{"class":46},"$IFS",[33,2345,807],{"class":57},[33,2347,2348],{"class":39},"   # still \" \\t\\n\" (default) — not changed\n",[33,2350,2351],{"class":35,"line":233},[33,2352,74],{"emptyLinePlaceholder":73},[33,2354,2355],{"class":35,"line":247},[33,2356,2357],{"class":39},"# ── Split on multiple delimiters ──\n",[33,2359,2360,2362,2364],{"class":35,"line":267},[33,2361,2235],{"class":46},[33,2363,51],{"class":50},[33,2365,2366],{"class":57},"\"a,b;c:d\"\n",[33,2368,2369,2371,2373,2376,2378,2380,2383,2385,2387,2389],{"class":35,"line":288},[33,2370,724],{"class":46},[33,2372,51],{"class":50},[33,2374,2375],{"class":57},"',;:'",[33,2377,1529],{"class":86},[33,2379,2263],{"class":86},[33,2381,2382],{"class":57}," parts",[33,2384,2269],{"class":50},[33,2386,801],{"class":57},[33,2388,2274],{"class":46},[33,2390,912],{"class":57},[33,2392,2393,2395,2397,2400,2402,2404,2406],{"class":35,"line":293},[33,2394,87],{"class":86},[33,2396,90],{"class":57},[33,2398,2399],{"class":46},"parts",[33,2401,140],{"class":57},[33,2403,143],{"class":50},[33,2405,146],{"class":57},[33,2407,2408],{"class":39},"   # a b c d — split on any of , ; :\n",[33,2410,2411],{"class":35,"line":299},[33,2412,74],{"emptyLinePlaceholder":73},[33,2414,2415],{"class":35,"line":318},[33,2416,2417],{"class":39},"# ── Array → string: join ──\n",[33,2419,2420,2422,2424,2426,2428,2430,2432],{"class":35,"line":339},[33,2421,465],{"class":46},[33,2423,51],{"class":50},[33,2425,54],{"class":46},[33,2427,58],{"class":57},[33,2429,61],{"class":57},[33,2431,64],{"class":57},[33,2433,67],{"class":46},[33,2435,2436],{"class":35,"line":344},[33,2437,74],{"emptyLinePlaceholder":73},[33,2439,2440],{"class":35,"line":350},[33,2441,2442],{"class":39},"# Method 1: default IFS join (space)\n",[33,2444,2445,2448,2450,2452,2454,2456,2458],{"class":35,"line":362},[33,2446,2447],{"class":46},"joined",[33,2449,51],{"class":50},[33,2451,1603],{"class":57},[33,2453,465],{"class":46},[33,2455,140],{"class":57},[33,2457,163],{"class":50},[33,2459,1322],{"class":57},[33,2461,2462,2464,2466,2469,2471],{"class":35,"line":380},[33,2463,87],{"class":86},[33,2465,801],{"class":57},[33,2467,2468],{"class":46},"$joined",[33,2470,807],{"class":57},[33,2472,2306],{"class":39},[33,2474,2475],{"class":35,"line":400},[33,2476,74],{"emptyLinePlaceholder":73},[33,2478,2479],{"class":35,"line":420},[33,2480,2481],{"class":39},"# Method 2: custom delimiter (temporary IFS change)\n",[33,2483,2484,2487],{"class":35,"line":721},[33,2485,2486],{"class":792},"join_by",[33,2488,1461],{"class":46},[33,2490,2491,2493,2496,2498,2501,2503],{"class":35,"line":732},[33,2492,1466],{"class":50},[33,2494,2495],{"class":46}," delim",[33,2497,51],{"class":50},[33,2499,1476],{"class":2500},"sCrzJ",[33,2502,517],{"class":46},[33,2504,2505],{"class":86},"shift\n",[33,2507,2508,2510,2513,2515,2517,2519],{"class":35,"line":750},[33,2509,1466],{"class":50},[33,2511,2512],{"class":46}," first",[33,2514,51],{"class":50},[33,2516,1476],{"class":2500},[33,2518,517],{"class":46},[33,2520,2505],{"class":86},[33,2522,2523,2525,2528,2530],{"class":35,"line":768},[33,2524,1466],{"class":50},[33,2526,2527],{"class":46}," result",[33,2529,51],{"class":50},[33,2531,2532],{"class":46},"$first\n",[33,2534,2535,2537],{"class":35,"line":778},[33,2536,1466],{"class":50},[33,2538,2539],{"class":46}," item\n",[33,2541,2542,2545,2548,2550,2552,2555,2557,2559],{"class":35,"line":783},[33,2543,2544],{"class":50},"    for",[33,2546,2547],{"class":46}," item ",[33,2549,504],{"class":50},[33,2551,801],{"class":57},[33,2553,2554],{"class":86},"$@",[33,2556,807],{"class":57},[33,2558,517],{"class":46},[33,2560,1301],{"class":50},[33,2562,2563,2566,2568,2570,2573],{"class":35,"line":789},[33,2564,2565],{"class":46},"        result",[33,2567,304],{"class":50},[33,2569,807],{"class":57},[33,2571,2572],{"class":46},"$delim$item",[33,2574,912],{"class":57},[33,2576,2577],{"class":35,"line":813},[33,2578,2579],{"class":50},"    done\n",[33,2581,2582,2585,2588,2590,2593],{"class":35,"line":831},[33,2583,2584],{"class":86},"    printf",[33,2586,2587],{"class":57}," '%s'",[33,2589,801],{"class":57},[33,2591,2592],{"class":46},"$result",[33,2594,912],{"class":57},[33,2596,2598],{"class":35,"line":2597},38,[33,2599,1698],{"class":46},[33,2601,2603,2605,2608,2610,2612,2614,2616,2618],{"class":35,"line":2602},39,[33,2604,2486],{"class":792},[33,2606,2607],{"class":57}," \", \"",[33,2609,90],{"class":57},[33,2611,465],{"class":46},[33,2613,140],{"class":57},[33,2615,143],{"class":50},[33,2617,146],{"class":57},[33,2619,2620],{"class":39},"   # apple, banana, cherry\n",[33,2622,2624],{"class":35,"line":2623},40,[33,2625,74],{"emptyLinePlaceholder":73},[33,2627,2629],{"class":35,"line":2628},41,[33,2630,2631],{"class":39},"# Method 3: IFS trick (one-liner, but affects global IFS temporarily)\n",[33,2633,2635,2637,2639],{"class":35,"line":2634},42,[33,2636,713],{"class":46},[33,2638,51],{"class":50},[33,2640,718],{"class":46},[33,2642,2644,2646,2648],{"class":35,"line":2643},43,[33,2645,724],{"class":46},[33,2647,51],{"class":50},[33,2649,2650],{"class":57},"', '\n",[33,2652,2654,2656,2658,2660,2662,2664,2666],{"class":35,"line":2653},44,[33,2655,2447],{"class":46},[33,2657,51],{"class":50},[33,2659,1603],{"class":57},[33,2661,465],{"class":46},[33,2663,140],{"class":57},[33,2665,163],{"class":50},[33,2667,1322],{"class":57},[33,2669,2671,2673,2675],{"class":35,"line":2670},45,[33,2672,724],{"class":46},[33,2674,51],{"class":50},[33,2676,775],{"class":46},[33,2678,2680,2682,2684,2686,2688],{"class":35,"line":2679},46,[33,2681,87],{"class":86},[33,2683,801],{"class":57},[33,2685,2468],{"class":46},[33,2687,807],{"class":57},[33,2689,2690],{"class":39},"   # apple, banana, cherry (IFS=',' joins with comma)\n",[15,2692,2694],{"id":2693},"slicing-and-splicing","Slicing and Splicing",[20,2696,2697],{"language":22},[24,2698,2700],{"className":26,"code":2699,"language":22,"meta":28,"style":28},"arr=(0 1 2 3 4 5 6 7 8 9)\n\n# ── Slice: ${arr[@]:start:length} ──\necho \"${arr[@]:2:3}\"    # 2 3 4 — from index 2, 3 elements\necho \"${arr[@]:5}\"      # 5 6 7 8 9 — from index 5 to end\necho \"${arr[@]: -3}\"    # 7 8 9 — last 3 (SPACE before - is required!)\necho \"${arr[@]:0-3}\"    # 7 8 9 — alternative: 0-3 (no space needed)\n\n# ── Slice to a new array ──\nsubset=(\"${arr[@]:2:3}\")  # subset = (2 3 4)\necho \"${subset[@]}\"       # 2 3 4\n\n# ── ⚠️ ${arr[@]: -3} vs ${arr[@]:-3} ──\n# ${arr[@]:-3}  → default expansion: if arr is empty, use \"3\" (the :- operator)\n# ${arr[@]: -3} → slice: last 3 elements (space before - makes it arithmetic)\n# Always use the space or 0-3 to avoid ambiguity.\n\n# ── Reindex after unset (remove gaps) ──\nsparse=([0]=\"a\" [5]=\"b\" [10]=\"c\")\nunset 'sparse[5]'     # remove element at index 5\necho \"${!sparse[@]}\"  # 0 10 — indices have a gap\nsparse=(\"${sparse[@]}\")  # reindex: contiguous 0 1\necho \"${!sparse[@]}\"  # 0 1 — reindexed\necho \"${sparse[0]}\"   # a\necho \"${sparse[1]}\"   # c\n",[30,2701,2702,2741,2745,2750,2781,2805,2829,2853,2857,2862,2897,2914,2918,2923,2928,2933,2938,2942,2947,2986,2996,3015,3038,3057,3070],{"__ignoreMap":28},[33,2703,2704,2706,2708,2710,2713,2715,2718,2721,2724,2727,2730,2733,2736,2739],{"class":35,"line":36},[33,2705,465],{"class":46},[33,2707,51],{"class":50},[33,2709,54],{"class":46},[33,2711,2712],{"class":86},"0",[33,2714,2146],{"class":86},[33,2716,2717],{"class":86}," 2",[33,2719,2720],{"class":86}," 3",[33,2722,2723],{"class":86}," 4",[33,2725,2726],{"class":86}," 5",[33,2728,2729],{"class":86}," 6",[33,2731,2732],{"class":86}," 7",[33,2734,2735],{"class":86}," 8",[33,2737,2738],{"class":86}," 9",[33,2740,67],{"class":46},[33,2742,2743],{"class":35,"line":43},[33,2744,74],{"emptyLinePlaceholder":73},[33,2746,2747],{"class":35,"line":70},[33,2748,2749],{"class":39},"# ── Slice: ${arr[@]:start:length} ──\n",[33,2751,2752,2754,2756,2758,2760,2762,2764,2767,2770,2772,2775,2778],{"class":35,"line":77},[33,2753,87],{"class":86},[33,2755,90],{"class":57},[33,2757,465],{"class":46},[33,2759,140],{"class":57},[33,2761,143],{"class":50},[33,2763,1143],{"class":57},[33,2765,2766],{"class":50},":",[33,2768,2769],{"class":46},"2",[33,2771,2766],{"class":50},[33,2773,2774],{"class":46},"3",[33,2776,2777],{"class":57},"}\"",[33,2779,2780],{"class":39},"    # 2 3 4 — from index 2, 3 elements\n",[33,2782,2783,2785,2787,2789,2791,2793,2795,2797,2800,2802],{"class":35,"line":83},[33,2784,87],{"class":86},[33,2786,90],{"class":57},[33,2788,465],{"class":46},[33,2790,140],{"class":57},[33,2792,143],{"class":50},[33,2794,1143],{"class":57},[33,2796,2766],{"class":50},[33,2798,2799],{"class":46},"5",[33,2801,2777],{"class":57},[33,2803,2804],{"class":39},"      # 5 6 7 8 9 — from index 5 to end\n",[33,2806,2807,2809,2811,2813,2815,2817,2819,2821,2824,2826],{"class":35,"line":101},[33,2808,87],{"class":86},[33,2810,90],{"class":57},[33,2812,465],{"class":46},[33,2814,140],{"class":57},[33,2816,143],{"class":50},[33,2818,1143],{"class":57},[33,2820,2766],{"class":50},[33,2822,2823],{"class":46}," -3",[33,2825,2777],{"class":57},[33,2827,2828],{"class":39},"    # 7 8 9 — last 3 (SPACE before - is required!)\n",[33,2830,2831,2833,2835,2837,2839,2841,2843,2845,2848,2850],{"class":35,"line":116},[33,2832,87],{"class":86},[33,2834,90],{"class":57},[33,2836,465],{"class":46},[33,2838,140],{"class":57},[33,2840,143],{"class":50},[33,2842,1143],{"class":57},[33,2844,2766],{"class":50},[33,2846,2847],{"class":46},"0-3",[33,2849,2777],{"class":57},[33,2851,2852],{"class":39},"    # 7 8 9 — alternative: 0-3 (no space needed)\n",[33,2854,2855],{"class":35,"line":131},[33,2856,74],{"emptyLinePlaceholder":73},[33,2858,2859],{"class":35,"line":152},[33,2860,2861],{"class":39},"# ── Slice to a new array ──\n",[33,2863,2864,2867,2869,2871,2873,2875,2877,2879,2881,2883,2885,2887,2889,2891,2894],{"class":35,"line":171},[33,2865,2866],{"class":46},"subset",[33,2868,51],{"class":50},[33,2870,54],{"class":46},[33,2872,1603],{"class":57},[33,2874,465],{"class":46},[33,2876,140],{"class":57},[33,2878,143],{"class":50},[33,2880,1143],{"class":57},[33,2882,2766],{"class":50},[33,2884,2769],{"class":46},[33,2886,2766],{"class":50},[33,2888,2774],{"class":46},[33,2890,2777],{"class":57},[33,2892,2893],{"class":46},")  ",[33,2895,2896],{"class":39},"# subset = (2 3 4)\n",[33,2898,2899,2901,2903,2905,2907,2909,2911],{"class":35,"line":192},[33,2900,87],{"class":86},[33,2902,90],{"class":57},[33,2904,2866],{"class":46},[33,2906,140],{"class":57},[33,2908,143],{"class":50},[33,2910,146],{"class":57},[33,2912,2913],{"class":39},"       # 2 3 4\n",[33,2915,2916],{"class":35,"line":208},[33,2917,74],{"emptyLinePlaceholder":73},[33,2919,2920],{"class":35,"line":213},[33,2921,2922],{"class":39},"# ── ⚠️ ${arr[@]: -3} vs ${arr[@]:-3} ──\n",[33,2924,2925],{"class":35,"line":219},[33,2926,2927],{"class":39},"# ${arr[@]:-3}  → default expansion: if arr is empty, use \"3\" (the :- operator)\n",[33,2929,2930],{"class":35,"line":233},[33,2931,2932],{"class":39},"# ${arr[@]: -3} → slice: last 3 elements (space before - makes it arithmetic)\n",[33,2934,2935],{"class":35,"line":247},[33,2936,2937],{"class":39},"# Always use the space or 0-3 to avoid ambiguity.\n",[33,2939,2940],{"class":35,"line":267},[33,2941,74],{"emptyLinePlaceholder":73},[33,2943,2944],{"class":35,"line":288},[33,2945,2946],{"class":39},"# ── Reindex after unset (remove gaps) ──\n",[33,2948,2949,2952,2954,2957,2959,2962,2964,2967,2969,2971,2974,2976,2979,2981,2984],{"class":35,"line":293},[33,2950,2951],{"class":46},"sparse",[33,2953,51],{"class":50},[33,2955,2956],{"class":46},"([",[33,2958,2712],{"class":792},[33,2960,2961],{"class":46},"]=",[33,2963,472],{"class":57},[33,2965,2966],{"class":46}," [",[33,2968,2799],{"class":792},[33,2970,2961],{"class":46},[33,2972,2973],{"class":57},"\"b\"",[33,2975,2966],{"class":46},[33,2977,2978],{"class":792},"10",[33,2980,2961],{"class":46},[33,2982,2983],{"class":57},"\"c\"",[33,2985,67],{"class":46},[33,2987,2988,2990,2993],{"class":35,"line":299},[33,2989,353],{"class":86},[33,2991,2992],{"class":57}," 'sparse[5]'",[33,2994,2995],{"class":39},"     # remove element at index 5\n",[33,2997,2998,3000,3002,3004,3006,3008,3010,3012],{"class":35,"line":318},[33,2999,87],{"class":86},[33,3001,90],{"class":57},[33,3003,274],{"class":50},[33,3005,2951],{"class":46},[33,3007,140],{"class":57},[33,3009,143],{"class":50},[33,3011,146],{"class":57},[33,3013,3014],{"class":39},"  # 0 10 — indices have a gap\n",[33,3016,3017,3019,3021,3023,3025,3027,3029,3031,3033,3035],{"class":35,"line":339},[33,3018,2951],{"class":46},[33,3020,51],{"class":50},[33,3022,54],{"class":46},[33,3024,1603],{"class":57},[33,3026,2951],{"class":46},[33,3028,140],{"class":57},[33,3030,143],{"class":50},[33,3032,146],{"class":57},[33,3034,2893],{"class":46},[33,3036,3037],{"class":39},"# reindex: contiguous 0 1\n",[33,3039,3040,3042,3044,3046,3048,3050,3052,3054],{"class":35,"line":344},[33,3041,87],{"class":86},[33,3043,90],{"class":57},[33,3045,274],{"class":50},[33,3047,2951],{"class":46},[33,3049,140],{"class":57},[33,3051,143],{"class":50},[33,3053,146],{"class":57},[33,3055,3056],{"class":39},"  # 0 1 — reindexed\n",[33,3058,3059,3061,3063,3065,3067],{"class":35,"line":350},[33,3060,87],{"class":86},[33,3062,90],{"class":57},[33,3064,2951],{"class":46},[33,3066,95],{"class":57},[33,3068,3069],{"class":39},"   # a\n",[33,3071,3072,3074,3076,3078,3080],{"class":35,"line":362},[33,3073,87],{"class":86},[33,3075,90],{"class":57},[33,3077,2951],{"class":46},[33,3079,110],{"class":57},[33,3081,3082],{"class":39},"   # c\n",[15,3084,3086],{"id":3085},"production-pattern-csv-processor","Production Pattern: CSV Processor",[20,3088,3089],{"language":22},[24,3090,3092],{"className":26,"code":3091,"language":22,"meta":28,"style":28},"#!\u002Fusr\u002Fbin\u002Fenv bash\n# ── Parse a CSV into an array of associative arrays (row → column → value) ──\n\nprocess_csv() {\n    local csv_file=$1\n    local -a headers=()\n    local -A row\n    local line_num=0\n\n    while IFS=, read -r line || [[ -n \"$line\" ]]; do\n        # Handle quoted CSV fields (basic — doesn't handle embedded commas in quotes)\n        # For proper CSV parsing, use csvkit or mlr\n\n        if ((line_num == 0)); then\n            # First line is the header\n            IFS=',' read -ra headers \u003C\u003C\u003C \"$line\"\n            ((line_num++))\n            continue\n        fi\n\n        # Split the data line\n        IFS=',' read -ra values \u003C\u003C\u003C \"$line\"\n\n        # Build associative array: header → value\n        row=()\n        for i in \"${!headers[@]}\"; do\n            row[\"${headers[i]}\"]=\"${values[i]:-}\"\n        done\n\n        # Process the row\n        printf '%s: %s\\n' \"${headers[0]}\" \"${row[${headers[0]}]}\"\n\n        ((line_num++))\n    done \u003C \"$csv_file\"\n}\n\n# CSV file:\n# name,age,city\n# Alice,30,NYC\n# Bob,25,LA\n\nprocess_csv data.csv\n# name: Alice\n# name: Bob\n",[30,3093,3094,3098,3103,3107,3114,3126,3141,3150,3162,3166,3204,3209,3214,3218,3238,3243,3266,3277,3282,3287,3291,3296,3320,3324,3329,3338,3365,3393,3398,3402,3407,3434,3438,3447,3460,3464,3468,3473,3478,3483,3488,3492,3499,3504],{"__ignoreMap":28},[33,3095,3096],{"class":35,"line":36},[33,3097,1441],{"class":39},[33,3099,3100],{"class":35,"line":43},[33,3101,3102],{"class":39},"# ── Parse a CSV into an array of associative arrays (row → column → value) ──\n",[33,3104,3105],{"class":35,"line":70},[33,3106,74],{"emptyLinePlaceholder":73},[33,3108,3109,3112],{"class":35,"line":77},[33,3110,3111],{"class":792},"process_csv",[33,3113,1461],{"class":46},[33,3115,3116,3118,3121,3123],{"class":35,"line":83},[33,3117,1466],{"class":50},[33,3119,3120],{"class":46}," csv_file",[33,3122,51],{"class":50},[33,3124,3125],{"class":2500},"$1\n",[33,3127,3128,3130,3133,3136,3138],{"class":35,"line":101},[33,3129,1466],{"class":50},[33,3131,3132],{"class":86}," -a",[33,3134,3135],{"class":46}," headers",[33,3137,51],{"class":50},[33,3139,3140],{"class":46},"()\n",[33,3142,3143,3145,3147],{"class":35,"line":116},[33,3144,1466],{"class":50},[33,3146,1090],{"class":86},[33,3148,3149],{"class":46}," row\n",[33,3151,3152,3154,3157,3159],{"class":35,"line":131},[33,3153,1466],{"class":50},[33,3155,3156],{"class":46}," line_num",[33,3158,51],{"class":50},[33,3160,3161],{"class":86},"0\n",[33,3163,3164],{"class":35,"line":152},[33,3165,74],{"emptyLinePlaceholder":73},[33,3167,3168,3170,3172,3174,3177,3179,3181,3184,3186,3189,3192,3194,3197,3199,3202],{"class":35,"line":171},[33,3169,1518],{"class":50},[33,3171,1521],{"class":46},[33,3173,51],{"class":50},[33,3175,3176],{"class":57},",",[33,3178,1529],{"class":86},[33,3180,1532],{"class":86},[33,3182,3183],{"class":57}," line",[33,3185,1564],{"class":50},[33,3187,3188],{"class":46}," [[ ",[33,3190,3191],{"class":50},"-n",[33,3193,801],{"class":57},[33,3195,3196],{"class":46},"$line",[33,3198,807],{"class":57},[33,3200,3201],{"class":46}," ]]; ",[33,3203,1301],{"class":50},[33,3205,3206],{"class":35,"line":192},[33,3207,3208],{"class":39},"        # Handle quoted CSV fields (basic — doesn't handle embedded commas in quotes)\n",[33,3210,3211],{"class":35,"line":208},[33,3212,3213],{"class":39},"        # For proper CSV parsing, use csvkit or mlr\n",[33,3215,3216],{"class":35,"line":213},[33,3217,74],{"emptyLinePlaceholder":73},[33,3219,3220,3223,3226,3229,3232,3235],{"class":35,"line":219},[33,3221,3222],{"class":50},"        if",[33,3224,3225],{"class":46}," ((line_num ",[33,3227,3228],{"class":50},"==",[33,3230,3231],{"class":86}," 0",[33,3233,3234],{"class":46},")); ",[33,3236,3237],{"class":50},"then\n",[33,3239,3240],{"class":35,"line":233},[33,3241,3242],{"class":39},"            # First line is the header\n",[33,3244,3245,3248,3250,3252,3254,3256,3258,3260,3262,3264],{"class":35,"line":247},[33,3246,3247],{"class":46},"            IFS",[33,3249,51],{"class":50},[33,3251,2258],{"class":57},[33,3253,1529],{"class":86},[33,3255,2263],{"class":86},[33,3257,3135],{"class":57},[33,3259,2269],{"class":50},[33,3261,801],{"class":57},[33,3263,3196],{"class":46},[33,3265,912],{"class":57},[33,3267,3268,3271,3274],{"class":35,"line":267},[33,3269,3270],{"class":46},"            ((line_num",[33,3272,3273],{"class":50},"++",[33,3275,3276],{"class":46},"))\n",[33,3278,3279],{"class":35,"line":288},[33,3280,3281],{"class":50},"            continue\n",[33,3283,3284],{"class":35,"line":293},[33,3285,3286],{"class":50},"        fi\n",[33,3288,3289],{"class":35,"line":299},[33,3290,74],{"emptyLinePlaceholder":73},[33,3292,3293],{"class":35,"line":318},[33,3294,3295],{"class":39},"        # Split the data line\n",[33,3297,3298,3301,3303,3305,3307,3309,3312,3314,3316,3318],{"class":35,"line":339},[33,3299,3300],{"class":46},"        IFS",[33,3302,51],{"class":50},[33,3304,2258],{"class":57},[33,3306,1529],{"class":86},[33,3308,2263],{"class":86},[33,3310,3311],{"class":57}," values",[33,3313,2269],{"class":50},[33,3315,801],{"class":57},[33,3317,3196],{"class":46},[33,3319,912],{"class":57},[33,3321,3322],{"class":35,"line":344},[33,3323,74],{"emptyLinePlaceholder":73},[33,3325,3326],{"class":35,"line":350},[33,3327,3328],{"class":39},"        # Build associative array: header → value\n",[33,3330,3331,3334,3336],{"class":35,"line":362},[33,3332,3333],{"class":46},"        row",[33,3335,51],{"class":50},[33,3337,3140],{"class":46},[33,3339,3340,3343,3346,3348,3350,3352,3355,3357,3359,3361,3363],{"class":35,"line":380},[33,3341,3342],{"class":50},"        for",[33,3344,3345],{"class":46}," i ",[33,3347,504],{"class":50},[33,3349,90],{"class":57},[33,3351,274],{"class":50},[33,3353,3354],{"class":46},"headers",[33,3356,140],{"class":57},[33,3358,143],{"class":50},[33,3360,146],{"class":57},[33,3362,517],{"class":46},[33,3364,1301],{"class":50},[33,3366,3367,3370,3372,3374,3377,3379,3381,3383,3386,3389,3391],{"class":35,"line":400},[33,3368,3369],{"class":792},"            row[",[33,3371,1603],{"class":792},[33,3373,3354],{"class":46},[33,3375,3376],{"class":792},"[i]}\"",[33,3378,1143],{"class":792},[33,3380,51],{"class":57},[33,3382,1603],{"class":792},[33,3384,3385],{"class":46},"values",[33,3387,3388],{"class":792},"[i]",[33,3390,1759],{"class":50},[33,3392,1615],{"class":792},[33,3394,3395],{"class":35,"line":420},[33,3396,3397],{"class":50},"        done\n",[33,3399,3400],{"class":35,"line":721},[33,3401,74],{"emptyLinePlaceholder":73},[33,3403,3404],{"class":35,"line":732},[33,3405,3406],{"class":39},"        # Process the row\n",[33,3408,3409,3412,3415,3417,3419,3421,3423,3426,3429,3431],{"class":35,"line":750},[33,3410,3411],{"class":86},"        printf",[33,3413,3414],{"class":57}," '%s: %s\\n'",[33,3416,90],{"class":57},[33,3418,3354],{"class":46},[33,3420,95],{"class":57},[33,3422,90],{"class":57},[33,3424,3425],{"class":46},"row",[33,3427,3428],{"class":57},"[${",[33,3430,3354],{"class":46},[33,3432,3433],{"class":57},"[0]}]}\"\n",[33,3435,3436],{"class":35,"line":768},[33,3437,74],{"emptyLinePlaceholder":73},[33,3439,3440,3443,3445],{"class":35,"line":778},[33,3441,3442],{"class":46},"        ((line_num",[33,3444,3273],{"class":50},[33,3446,3276],{"class":46},[33,3448,3449,3451,3453,3455,3458],{"class":35,"line":783},[33,3450,1684],{"class":50},[33,3452,1687],{"class":50},[33,3454,801],{"class":57},[33,3456,3457],{"class":46},"$csv_file",[33,3459,912],{"class":57},[33,3461,3462],{"class":35,"line":789},[33,3463,1698],{"class":46},[33,3465,3466],{"class":35,"line":813},[33,3467,74],{"emptyLinePlaceholder":73},[33,3469,3470],{"class":35,"line":831},[33,3471,3472],{"class":39},"# CSV file:\n",[33,3474,3475],{"class":35,"line":2597},[33,3476,3477],{"class":39},"# name,age,city\n",[33,3479,3480],{"class":35,"line":2602},[33,3481,3482],{"class":39},"# Alice,30,NYC\n",[33,3484,3485],{"class":35,"line":2623},[33,3486,3487],{"class":39},"# Bob,25,LA\n",[33,3489,3490],{"class":35,"line":2628},[33,3491,74],{"emptyLinePlaceholder":73},[33,3493,3494,3496],{"class":35,"line":2634},[33,3495,3111],{"class":792},[33,3497,3498],{"class":57}," data.csv\n",[33,3500,3501],{"class":35,"line":2643},[33,3502,3503],{"class":39},"# name: Alice\n",[33,3505,3506],{"class":35,"line":2653},[33,3507,3508],{"class":39},"# name: Bob\n",[15,3510,3512],{"id":3511},"tips-tricks","💡 Tips & Tricks",[20,3514,3515],{"language":22},[24,3516,3518],{"className":26,"code":3517,"language":22,"meta":28,"style":28},"# ── Simulate a stack with array ──\nstack=()\npush() { stack+=(\"$1\"); }      # append to end\npop() {\n    local -n _s=$1\n    local last=${_s[-1]}\n    unset '_s[-1]'\n    _s=(\"${_s[@]}\")             # reindex (remove gap)\n    echo \"$last\"\n}\npush \"first\"\npush \"second\"\npop stack   # second\npop stack   # first\n\n# ── Simulate a queue ──\nqueue=()\nenqueue() { queue+=(\"$1\"); }   # append to end\ndequeue() {\n    local first=${queue[0]}\n    unset 'queue[0]'\n    queue=(\"${queue[@]}\")       # reindex\n    echo \"$first\"\n}\n\n# ── Flatten a nested array (Bash has no real nesting) ──\n# Use a naming convention: arr_0, arr_1, etc.\n# Or store as strings with a delimiter:\ndeclare -A matrix\nmatrix[\"0_0\"]=\"a\"   matrix[\"0_1\"]=\"b\"\nmatrix[\"1_0\"]=\"c\"   matrix[\"1_1\"]=\"d\"\n# Access: echo \"${matrix[\"${row}_${col}\"]}\"\n\n# ── Array of arrays via namerefs ──\ndeclare -A arrays\narr1=(1 2 3)\narr2=(4 5 6)\narrays[\"set1\"]=arr1   # store the NAME, not the array (can't store arrays in arrays)\narrays[\"set2\"]=arr2\n\nget_array() {\n    local -n _result=$1\n    local name=${arrays[$2]}   # get the array name\n    local -n _src=$name         # nameref to the source array\n    _result=(\"${_src[@]}\")      # copy into caller's array\n}\nget_array my_arr \"set1\"\necho \"${my_arr[@]}\"   # 1 2 3\n\n# ── Dedup an array (preserve order) ──\ndedup_array() {\n    local -n _arr=$1\n    local -A seen=()\n    local -A result=()\n    local item\n    for item in \"${_arr[@]}\"; do\n        [[ -v seen[$item] ]] && continue\n        seen[$item]=1\n        result+=(\"$item\")\n    done\n    _arr=(\"${result[@]}\")\n}\narr=(a b a c b d)\ndedup_array arr\necho \"${arr[@]}\"   # a b c d\n",[30,3519,3520,3525,3534,3558,3565,3578,3590,3598,3624,3635,3639,3646,3653,3663,3672,3676,3681,3690,3713,3720,3731,3738,3762,3773,3777,3781,3786,3791,3796,3805,3822,3838,3843,3847,3852,3861,3879,3897,3913,3925,3929,3936,3949,3970,3987,4012,4016,4027,4046,4051,4057,4065,4079,4093,4106,4113,4137,4145,4156,4174,4179,4202,4207,4235,4243],{"__ignoreMap":28},[33,3521,3522],{"class":35,"line":36},[33,3523,3524],{"class":39},"# ── Simulate a stack with array ──\n",[33,3526,3527,3530,3532],{"class":35,"line":43},[33,3528,3529],{"class":46},"stack",[33,3531,51],{"class":50},[33,3533,3140],{"class":46},[33,3535,3536,3539,3542,3544,3546,3548,3550,3552,3555],{"class":35,"line":70},[33,3537,3538],{"class":792},"push",[33,3540,3541],{"class":46},"() { stack",[33,3543,304],{"class":50},[33,3545,54],{"class":46},[33,3547,807],{"class":57},[33,3549,1476],{"class":86},[33,3551,807],{"class":57},[33,3553,3554],{"class":46},"); }      ",[33,3556,3557],{"class":39},"# append to end\n",[33,3559,3560,3563],{"class":35,"line":77},[33,3561,3562],{"class":792},"pop",[33,3564,1461],{"class":46},[33,3566,3567,3569,3571,3574,3576],{"class":35,"line":83},[33,3568,1466],{"class":50},[33,3570,2173],{"class":86},[33,3572,3573],{"class":46}," _s",[33,3575,51],{"class":50},[33,3577,3125],{"class":2500},[33,3579,3580,3582,3585,3587],{"class":35,"line":101},[33,3581,1466],{"class":50},[33,3583,3584],{"class":46}," last",[33,3586,51],{"class":50},[33,3588,3589],{"class":46},"${_s[-1]}\n",[33,3591,3592,3595],{"class":35,"line":116},[33,3593,3594],{"class":86},"    unset",[33,3596,3597],{"class":57}," '_s[-1]'\n",[33,3599,3600,3603,3605,3607,3609,3612,3614,3616,3618,3621],{"class":35,"line":131},[33,3601,3602],{"class":46},"    _s",[33,3604,51],{"class":50},[33,3606,54],{"class":46},[33,3608,1603],{"class":57},[33,3610,3611],{"class":46},"_s",[33,3613,140],{"class":57},[33,3615,143],{"class":50},[33,3617,146],{"class":57},[33,3619,3620],{"class":46},")             ",[33,3622,3623],{"class":39},"# reindex (remove gap)\n",[33,3625,3626,3628,3630,3633],{"class":35,"line":152},[33,3627,904],{"class":86},[33,3629,801],{"class":57},[33,3631,3632],{"class":46},"$last",[33,3634,912],{"class":57},[33,3636,3637],{"class":35,"line":171},[33,3638,1698],{"class":46},[33,3640,3641,3643],{"class":35,"line":192},[33,3642,3538],{"class":792},[33,3644,3645],{"class":57}," \"first\"\n",[33,3647,3648,3650],{"class":35,"line":208},[33,3649,3538],{"class":792},[33,3651,3652],{"class":57}," \"second\"\n",[33,3654,3655,3657,3660],{"class":35,"line":213},[33,3656,3562],{"class":792},[33,3658,3659],{"class":57}," stack",[33,3661,3662],{"class":39},"   # second\n",[33,3664,3665,3667,3669],{"class":35,"line":219},[33,3666,3562],{"class":792},[33,3668,3659],{"class":57},[33,3670,3671],{"class":39},"   # first\n",[33,3673,3674],{"class":35,"line":233},[33,3675,74],{"emptyLinePlaceholder":73},[33,3677,3678],{"class":35,"line":247},[33,3679,3680],{"class":39},"# ── Simulate a queue ──\n",[33,3682,3683,3686,3688],{"class":35,"line":267},[33,3684,3685],{"class":46},"queue",[33,3687,51],{"class":50},[33,3689,3140],{"class":46},[33,3691,3692,3695,3698,3700,3702,3704,3706,3708,3711],{"class":35,"line":288},[33,3693,3694],{"class":792},"enqueue",[33,3696,3697],{"class":46},"() { queue",[33,3699,304],{"class":50},[33,3701,54],{"class":46},[33,3703,807],{"class":57},[33,3705,1476],{"class":86},[33,3707,807],{"class":57},[33,3709,3710],{"class":46},"); }   ",[33,3712,3557],{"class":39},[33,3714,3715,3718],{"class":35,"line":293},[33,3716,3717],{"class":792},"dequeue",[33,3719,1461],{"class":46},[33,3721,3722,3724,3726,3728],{"class":35,"line":299},[33,3723,1466],{"class":50},[33,3725,2512],{"class":46},[33,3727,51],{"class":50},[33,3729,3730],{"class":46},"${queue[0]}\n",[33,3732,3733,3735],{"class":35,"line":318},[33,3734,3594],{"class":86},[33,3736,3737],{"class":57}," 'queue[0]'\n",[33,3739,3740,3743,3745,3747,3749,3751,3753,3755,3757,3759],{"class":35,"line":339},[33,3741,3742],{"class":46},"    queue",[33,3744,51],{"class":50},[33,3746,54],{"class":46},[33,3748,1603],{"class":57},[33,3750,3685],{"class":46},[33,3752,140],{"class":57},[33,3754,143],{"class":50},[33,3756,146],{"class":57},[33,3758,312],{"class":46},[33,3760,3761],{"class":39},"# reindex\n",[33,3763,3764,3766,3768,3771],{"class":35,"line":344},[33,3765,904],{"class":86},[33,3767,801],{"class":57},[33,3769,3770],{"class":46},"$first",[33,3772,912],{"class":57},[33,3774,3775],{"class":35,"line":350},[33,3776,1698],{"class":46},[33,3778,3779],{"class":35,"line":362},[33,3780,74],{"emptyLinePlaceholder":73},[33,3782,3783],{"class":35,"line":380},[33,3784,3785],{"class":39},"# ── Flatten a nested array (Bash has no real nesting) ──\n",[33,3787,3788],{"class":35,"line":400},[33,3789,3790],{"class":39},"# Use a naming convention: arr_0, arr_1, etc.\n",[33,3792,3793],{"class":35,"line":420},[33,3794,3795],{"class":39},"# Or store as strings with a delimiter:\n",[33,3797,3798,3800,3802],{"class":35,"line":721},[33,3799,1087],{"class":50},[33,3801,1090],{"class":86},[33,3803,3804],{"class":46}," matrix\n",[33,3806,3807,3810,3813,3815,3817,3819],{"class":35,"line":732},[33,3808,3809],{"class":792},"matrix[",[33,3811,3812],{"class":792},"\"0_0\"",[33,3814,1143],{"class":792},[33,3816,51],{"class":57},[33,3818,472],{"class":792},[33,3820,3821],{"class":57},"   matrix[\"0_1\"]=\"b\"\n",[33,3823,3824,3826,3829,3831,3833,3835],{"class":35,"line":750},[33,3825,3809],{"class":792},[33,3827,3828],{"class":792},"\"1_0\"",[33,3830,1143],{"class":792},[33,3832,51],{"class":57},[33,3834,2983],{"class":792},[33,3836,3837],{"class":57},"   matrix[\"1_1\"]=\"d\"\n",[33,3839,3840],{"class":35,"line":768},[33,3841,3842],{"class":39},"# Access: echo \"${matrix[\"${row}_${col}\"]}\"\n",[33,3844,3845],{"class":35,"line":778},[33,3846,74],{"emptyLinePlaceholder":73},[33,3848,3849],{"class":35,"line":783},[33,3850,3851],{"class":39},"# ── Array of arrays via namerefs ──\n",[33,3853,3854,3856,3858],{"class":35,"line":789},[33,3855,1087],{"class":50},[33,3857,1090],{"class":86},[33,3859,3860],{"class":46}," arrays\n",[33,3862,3863,3866,3868,3870,3873,3875,3877],{"class":35,"line":813},[33,3864,3865],{"class":46},"arr1",[33,3867,51],{"class":50},[33,3869,54],{"class":46},[33,3871,3872],{"class":86},"1",[33,3874,2717],{"class":86},[33,3876,2720],{"class":86},[33,3878,67],{"class":46},[33,3880,3881,3884,3886,3888,3891,3893,3895],{"class":35,"line":831},[33,3882,3883],{"class":46},"arr2",[33,3885,51],{"class":50},[33,3887,54],{"class":46},[33,3889,3890],{"class":86},"4",[33,3892,2726],{"class":86},[33,3894,2729],{"class":86},[33,3896,67],{"class":46},[33,3898,3899,3902,3905,3907,3910],{"class":35,"line":2597},[33,3900,3901],{"class":792},"arrays[",[33,3903,3904],{"class":792},"\"set1\"",[33,3906,1143],{"class":792},[33,3908,3909],{"class":57},"=arr1",[33,3911,3912],{"class":39},"   # store the NAME, not the array (can't store arrays in arrays)\n",[33,3914,3915,3917,3920,3922],{"class":35,"line":2602},[33,3916,3901],{"class":792},[33,3918,3919],{"class":792},"\"set2\"",[33,3921,1143],{"class":792},[33,3923,3924],{"class":57},"=arr2\n",[33,3926,3927],{"class":35,"line":2623},[33,3928,74],{"emptyLinePlaceholder":73},[33,3930,3931,3934],{"class":35,"line":2628},[33,3932,3933],{"class":792},"get_array",[33,3935,1461],{"class":46},[33,3937,3938,3940,3942,3945,3947],{"class":35,"line":2634},[33,3939,1466],{"class":50},[33,3941,2173],{"class":86},[33,3943,3944],{"class":46}," _result",[33,3946,51],{"class":50},[33,3948,3125],{"class":2500},[33,3950,3951,3953,3956,3958,3961,3964,3967],{"class":35,"line":2643},[33,3952,1466],{"class":50},[33,3954,3955],{"class":46}," name",[33,3957,51],{"class":50},[33,3959,3960],{"class":46},"${arrays[",[33,3962,3963],{"class":2500},"$2",[33,3965,3966],{"class":46},"]}   ",[33,3968,3969],{"class":39},"# get the array name\n",[33,3971,3972,3974,3976,3979,3981,3984],{"class":35,"line":2653},[33,3973,1466],{"class":50},[33,3975,2173],{"class":86},[33,3977,3978],{"class":46}," _src",[33,3980,51],{"class":50},[33,3982,3983],{"class":46},"$name         ",[33,3985,3986],{"class":39},"# nameref to the source array\n",[33,3988,3989,3992,3994,3996,3998,4001,4003,4005,4007,4009],{"class":35,"line":2670},[33,3990,3991],{"class":46},"    _result",[33,3993,51],{"class":50},[33,3995,54],{"class":46},[33,3997,1603],{"class":57},[33,3999,4000],{"class":46},"_src",[33,4002,140],{"class":57},[33,4004,143],{"class":50},[33,4006,146],{"class":57},[33,4008,333],{"class":46},[33,4010,4011],{"class":39},"# copy into caller's array\n",[33,4013,4014],{"class":35,"line":2679},[33,4015,1698],{"class":46},[33,4017,4019,4021,4024],{"class":35,"line":4018},47,[33,4020,3933],{"class":792},[33,4022,4023],{"class":57}," my_arr",[33,4025,4026],{"class":57}," \"set1\"\n",[33,4028,4030,4032,4034,4037,4039,4041,4043],{"class":35,"line":4029},48,[33,4031,87],{"class":86},[33,4033,90],{"class":57},[33,4035,4036],{"class":46},"my_arr",[33,4038,140],{"class":57},[33,4040,143],{"class":50},[33,4042,146],{"class":57},[33,4044,4045],{"class":39},"   # 1 2 3\n",[33,4047,4049],{"class":35,"line":4048},49,[33,4050,74],{"emptyLinePlaceholder":73},[33,4052,4054],{"class":35,"line":4053},50,[33,4055,4056],{"class":39},"# ── Dedup an array (preserve order) ──\n",[33,4058,4060,4063],{"class":35,"line":4059},51,[33,4061,4062],{"class":792},"dedup_array",[33,4064,1461],{"class":46},[33,4066,4068,4070,4072,4075,4077],{"class":35,"line":4067},52,[33,4069,1466],{"class":50},[33,4071,2173],{"class":86},[33,4073,4074],{"class":46}," _arr",[33,4076,51],{"class":50},[33,4078,3125],{"class":2500},[33,4080,4082,4084,4086,4089,4091],{"class":35,"line":4081},53,[33,4083,1466],{"class":50},[33,4085,1090],{"class":86},[33,4087,4088],{"class":46}," seen",[33,4090,51],{"class":50},[33,4092,3140],{"class":46},[33,4094,4096,4098,4100,4102,4104],{"class":35,"line":4095},54,[33,4097,1466],{"class":50},[33,4099,1090],{"class":86},[33,4101,2527],{"class":46},[33,4103,51],{"class":50},[33,4105,3140],{"class":46},[33,4107,4109,4111],{"class":35,"line":4108},55,[33,4110,1466],{"class":50},[33,4112,2539],{"class":46},[33,4114,4116,4118,4120,4122,4124,4127,4129,4131,4133,4135],{"class":35,"line":4115},56,[33,4117,2544],{"class":50},[33,4119,2547],{"class":46},[33,4121,504],{"class":50},[33,4123,90],{"class":57},[33,4125,4126],{"class":46},"_arr",[33,4128,140],{"class":57},[33,4130,143],{"class":50},[33,4132,146],{"class":57},[33,4134,517],{"class":46},[33,4136,1301],{"class":50},[33,4138,4140,4143],{"class":35,"line":4139},57,[33,4141,4142],{"class":46},"        [[ -v seen[$item] ]] && ",[33,4144,1584],{"class":50},[33,4146,4148,4151,4153],{"class":35,"line":4147},58,[33,4149,4150],{"class":46},"        seen[$item]",[33,4152,51],{"class":50},[33,4154,4155],{"class":57},"1\n",[33,4157,4159,4161,4163,4165,4167,4170,4172],{"class":35,"line":4158},59,[33,4160,2565],{"class":46},[33,4162,304],{"class":50},[33,4164,54],{"class":46},[33,4166,807],{"class":57},[33,4168,4169],{"class":46},"$item",[33,4171,807],{"class":57},[33,4173,67],{"class":46},[33,4175,4177],{"class":35,"line":4176},60,[33,4178,2579],{"class":50},[33,4180,4182,4185,4187,4189,4191,4194,4196,4198,4200],{"class":35,"line":4181},61,[33,4183,4184],{"class":46},"    _arr",[33,4186,51],{"class":50},[33,4188,54],{"class":46},[33,4190,1603],{"class":57},[33,4192,4193],{"class":46},"result",[33,4195,140],{"class":57},[33,4197,143],{"class":50},[33,4199,146],{"class":57},[33,4201,67],{"class":46},[33,4203,4205],{"class":35,"line":4204},62,[33,4206,1698],{"class":46},[33,4208,4210,4212,4214,4216,4219,4222,4225,4228,4230,4233],{"class":35,"line":4209},63,[33,4211,465],{"class":46},[33,4213,51],{"class":50},[33,4215,54],{"class":46},[33,4217,4218],{"class":57},"a",[33,4220,4221],{"class":57}," b",[33,4223,4224],{"class":57}," a",[33,4226,4227],{"class":57}," c",[33,4229,4221],{"class":57},[33,4231,4232],{"class":57}," d",[33,4234,67],{"class":46},[33,4236,4238,4240],{"class":35,"line":4237},64,[33,4239,4062],{"class":792},[33,4241,4242],{"class":57}," arr\n",[33,4244,4246,4248,4250,4252,4254,4256,4258],{"class":35,"line":4245},65,[33,4247,87],{"class":86},[33,4249,90],{"class":57},[33,4251,465],{"class":46},[33,4253,140],{"class":57},[33,4255,143],{"class":50},[33,4257,146],{"class":57},[33,4259,4260],{"class":39},"   # a b c d\n",[15,4262,4264],{"id":4263},"️-edge-cases-gotchas","⚠️ Edge Cases & Gotchas",[20,4266,4267],{"language":22},[24,4268,4270],{"className":26,"code":4269,"language":22,"meta":28,"style":28},"# ── `unset 'arr[i]'` leaves a gap ──\narr=(a b c d)\nunset 'arr[1]'       # remove \"b\"\necho \"${arr[@]}\"     # a c d — value gone\necho \"${!arr[@]}\"    # 0 2 3 — index 1 is a GAP\necho \"${#arr[@]}\"    # 3 — count excludes gap\n# Reindex: arr=(\"${arr[@]}\")  → indices 0 1 2\n\n# ── `\"${arr[@]: -1}\"` needs a space (Bash \u003C 4.3) ──\necho \"${arr[@]: -1}\"  # last element (space before -)\necho \"${arr[@]:0-1}\"  # also last element (0-1 is arithmetic)\necho \"${arr[-1]}\"     # last element (Bash 4.3+ — no [@] needed)\n\n# ── Associative arrays are UNORDERED ──\ndeclare -A m=([z]=1 [a]=2 [m]=3)\necho \"${!m[@]}\"       # z a m OR a z m OR ... — order is hash-dependent, NOT insertion order\n# If you need ordered keys, maintain a separate indexed array of keys:\nkeys=(\"z\" \"a\" \"m\")   # explicit order\nfor k in \"${keys[@]}\"; do echo \"$k = ${m[$k]}\"; done\n\n# ── `arr+=\"x\"` appends to arr[0], NOT as a new element ──\narr=(\"a\" \"b\")\narr+=\"c\"             # ❌ arr is now (\"ac\" \"b\") — string append to first element!\narr+=(\"c\")           # ✅ arr is now (\"a\" \"b\" \"c\") — array append (parentheses required)\n\n# ── `read -a` in a pipeline runs in a subshell ──\necho \"a b c\" | read -a arr   # arr is set in the SUBSHELL — lost after!\necho \"${arr[@]}\"             # empty — subshell didn't leak\n# Fix: read -a arr \u003C\u003C\u003C \"a b c\"  (here-string — no subshell)\n\n# ── `local -n arr=$1` circular reference ──\nfunc() { local -n arr=$1; echo \"${arr[@]}\"; }\narr=(1 2 3)\nfunc arr   # ✗ circular name reference (arr references itself)\n# Fix: func() { local -n _ref=$1; echo \"${_ref[@]}\"; }\n\n# ── Empty array with `set -u` (Bash \u003C 4.4) ──\nset -u\narr=()\necho \"${arr[@]}\"   # Bash 4.4+: OK (empty). Bash \u003C 4.4: unbound variable error!\n# Fix: echo \"${arr[@]:-}\"\n",[30,4271,4272,4277,4295,4305,4322,4341,4360,4365,4369,4374,4398,4422,4435,4439,4444,4483,4502,4507,4530,4574,4578,4583,4598,4609,4625,4629,4634,4653,4670,4675,4679,4684,4718,4734,4743,4748,4752,4757,4765,4773,4790],{"__ignoreMap":28},[33,4273,4274],{"class":35,"line":36},[33,4275,4276],{"class":39},"# ── `unset 'arr[i]'` leaves a gap ──\n",[33,4278,4279,4281,4283,4285,4287,4289,4291,4293],{"class":35,"line":43},[33,4280,465],{"class":46},[33,4282,51],{"class":50},[33,4284,54],{"class":46},[33,4286,4218],{"class":57},[33,4288,4221],{"class":57},[33,4290,4227],{"class":57},[33,4292,4232],{"class":57},[33,4294,67],{"class":46},[33,4296,4297,4299,4302],{"class":35,"line":70},[33,4298,353],{"class":86},[33,4300,4301],{"class":57}," 'arr[1]'",[33,4303,4304],{"class":39},"       # remove \"b\"\n",[33,4306,4307,4309,4311,4313,4315,4317,4319],{"class":35,"line":77},[33,4308,87],{"class":86},[33,4310,90],{"class":57},[33,4312,465],{"class":46},[33,4314,140],{"class":57},[33,4316,143],{"class":50},[33,4318,146],{"class":57},[33,4320,4321],{"class":39},"     # a c d — value gone\n",[33,4323,4324,4326,4328,4330,4332,4334,4336,4338],{"class":35,"line":83},[33,4325,87],{"class":86},[33,4327,90],{"class":57},[33,4329,274],{"class":50},[33,4331,465],{"class":46},[33,4333,140],{"class":57},[33,4335,143],{"class":50},[33,4337,146],{"class":57},[33,4339,4340],{"class":39},"    # 0 2 3 — index 1 is a GAP\n",[33,4342,4343,4345,4347,4349,4351,4353,4355,4357],{"class":35,"line":101},[33,4344,87],{"class":86},[33,4346,90],{"class":57},[33,4348,178],{"class":50},[33,4350,465],{"class":46},[33,4352,140],{"class":57},[33,4354,143],{"class":50},[33,4356,146],{"class":57},[33,4358,4359],{"class":39},"    # 3 — count excludes gap\n",[33,4361,4362],{"class":35,"line":116},[33,4363,4364],{"class":39},"# Reindex: arr=(\"${arr[@]}\")  → indices 0 1 2\n",[33,4366,4367],{"class":35,"line":131},[33,4368,74],{"emptyLinePlaceholder":73},[33,4370,4371],{"class":35,"line":152},[33,4372,4373],{"class":39},"# ── `\"${arr[@]: -1}\"` needs a space (Bash \u003C 4.3) ──\n",[33,4375,4376,4378,4380,4382,4384,4386,4388,4390,4393,4395],{"class":35,"line":171},[33,4377,87],{"class":86},[33,4379,90],{"class":57},[33,4381,465],{"class":46},[33,4383,140],{"class":57},[33,4385,143],{"class":50},[33,4387,1143],{"class":57},[33,4389,2766],{"class":50},[33,4391,4392],{"class":46}," -1",[33,4394,2777],{"class":57},[33,4396,4397],{"class":39},"  # last element (space before -)\n",[33,4399,4400,4402,4404,4406,4408,4410,4412,4414,4417,4419],{"class":35,"line":192},[33,4401,87],{"class":86},[33,4403,90],{"class":57},[33,4405,465],{"class":46},[33,4407,140],{"class":57},[33,4409,143],{"class":50},[33,4411,1143],{"class":57},[33,4413,2766],{"class":50},[33,4415,4416],{"class":46},"0-1",[33,4418,2777],{"class":57},[33,4420,4421],{"class":39},"  # also last element (0-1 is arithmetic)\n",[33,4423,4424,4426,4428,4430,4432],{"class":35,"line":208},[33,4425,87],{"class":86},[33,4427,90],{"class":57},[33,4429,465],{"class":46},[33,4431,125],{"class":57},[33,4433,4434],{"class":39},"     # last element (Bash 4.3+ — no [@] needed)\n",[33,4436,4437],{"class":35,"line":213},[33,4438,74],{"emptyLinePlaceholder":73},[33,4440,4441],{"class":35,"line":219},[33,4442,4443],{"class":39},"# ── Associative arrays are UNORDERED ──\n",[33,4445,4446,4448,4450,4453,4455,4457,4460,4462,4464,4466,4468,4470,4472,4474,4477,4479,4481],{"class":35,"line":233},[33,4447,1087],{"class":50},[33,4449,1090],{"class":86},[33,4451,4452],{"class":46}," m",[33,4454,51],{"class":50},[33,4456,2956],{"class":46},[33,4458,4459],{"class":792},"z",[33,4461,2961],{"class":46},[33,4463,3872],{"class":86},[33,4465,2966],{"class":46},[33,4467,4218],{"class":792},[33,4469,2961],{"class":46},[33,4471,2769],{"class":86},[33,4473,2966],{"class":46},[33,4475,4476],{"class":792},"m",[33,4478,2961],{"class":46},[33,4480,2774],{"class":86},[33,4482,67],{"class":46},[33,4484,4485,4487,4489,4491,4493,4495,4497,4499],{"class":35,"line":247},[33,4486,87],{"class":86},[33,4488,90],{"class":57},[33,4490,274],{"class":50},[33,4492,4476],{"class":46},[33,4494,140],{"class":57},[33,4496,143],{"class":50},[33,4498,146],{"class":57},[33,4500,4501],{"class":39},"       # z a m OR a z m OR ... — order is hash-dependent, NOT insertion order\n",[33,4503,4504],{"class":35,"line":267},[33,4505,4506],{"class":39},"# If you need ordered keys, maintain a separate indexed array of keys:\n",[33,4508,4509,4512,4514,4516,4519,4522,4525,4527],{"class":35,"line":288},[33,4510,4511],{"class":46},"keys",[33,4513,51],{"class":50},[33,4515,54],{"class":46},[33,4517,4518],{"class":57},"\"z\"",[33,4520,4521],{"class":57}," \"a\"",[33,4523,4524],{"class":57}," \"m\"",[33,4526,481],{"class":46},[33,4528,4529],{"class":39},"# explicit order\n",[33,4531,4532,4534,4537,4539,4541,4543,4545,4547,4549,4551,4553,4555,4557,4560,4562,4564,4566,4568,4570,4572],{"class":35,"line":293},[33,4533,498],{"class":50},[33,4535,4536],{"class":46}," k ",[33,4538,504],{"class":50},[33,4540,90],{"class":57},[33,4542,4511],{"class":46},[33,4544,140],{"class":57},[33,4546,143],{"class":50},[33,4548,146],{"class":57},[33,4550,517],{"class":46},[33,4552,520],{"class":50},[33,4554,523],{"class":86},[33,4556,801],{"class":57},[33,4558,4559],{"class":46},"$k",[33,4561,1313],{"class":57},[33,4563,4476],{"class":46},[33,4565,140],{"class":57},[33,4567,4559],{"class":46},[33,4569,146],{"class":57},[33,4571,517],{"class":46},[33,4573,537],{"class":50},[33,4575,4576],{"class":35,"line":299},[33,4577,74],{"emptyLinePlaceholder":73},[33,4579,4580],{"class":35,"line":318},[33,4581,4582],{"class":39},"# ── `arr+=\"x\"` appends to arr[0], NOT as a new element ──\n",[33,4584,4585,4587,4589,4591,4593,4596],{"class":35,"line":339},[33,4586,465],{"class":46},[33,4588,51],{"class":50},[33,4590,54],{"class":46},[33,4592,472],{"class":57},[33,4594,4595],{"class":57}," \"b\"",[33,4597,67],{"class":46},[33,4599,4600,4602,4604,4606],{"class":35,"line":344},[33,4601,465],{"class":46},[33,4603,304],{"class":50},[33,4605,2983],{"class":57},[33,4607,4608],{"class":39},"             # ❌ arr is now (\"ac\" \"b\") — string append to first element!\n",[33,4610,4611,4613,4615,4617,4619,4622],{"class":35,"line":350},[33,4612,465],{"class":46},[33,4614,304],{"class":50},[33,4616,54],{"class":46},[33,4618,2983],{"class":57},[33,4620,4621],{"class":46},")           ",[33,4623,4624],{"class":39},"# ✅ arr is now (\"a\" \"b\" \"c\") — array append (parentheses required)\n",[33,4626,4627],{"class":35,"line":362},[33,4628,74],{"emptyLinePlaceholder":73},[33,4630,4631],{"class":35,"line":380},[33,4632,4633],{"class":39},"# ── `read -a` in a pipeline runs in a subshell ──\n",[33,4635,4636,4638,4641,4643,4645,4647,4650],{"class":35,"line":400},[33,4637,87],{"class":86},[33,4639,4640],{"class":57}," \"a b c\"",[33,4642,1993],{"class":50},[33,4644,1529],{"class":86},[33,4646,3132],{"class":86},[33,4648,4649],{"class":57}," arr",[33,4651,4652],{"class":39},"   # arr is set in the SUBSHELL — lost after!\n",[33,4654,4655,4657,4659,4661,4663,4665,4667],{"class":35,"line":420},[33,4656,87],{"class":86},[33,4658,90],{"class":57},[33,4660,465],{"class":46},[33,4662,140],{"class":57},[33,4664,143],{"class":50},[33,4666,146],{"class":57},[33,4668,4669],{"class":39},"             # empty — subshell didn't leak\n",[33,4671,4672],{"class":35,"line":721},[33,4673,4674],{"class":39},"# Fix: read -a arr \u003C\u003C\u003C \"a b c\"  (here-string — no subshell)\n",[33,4676,4677],{"class":35,"line":732},[33,4678,74],{"emptyLinePlaceholder":73},[33,4680,4681],{"class":35,"line":750},[33,4682,4683],{"class":39},"# ── `local -n arr=$1` circular reference ──\n",[33,4685,4686,4689,4691,4694,4696,4698,4700,4702,4704,4706,4708,4710,4712,4714,4716],{"class":35,"line":768},[33,4687,4688],{"class":792},"func",[33,4690,796],{"class":46},[33,4692,4693],{"class":50},"local",[33,4695,2173],{"class":86},[33,4697,4649],{"class":46},[33,4699,51],{"class":50},[33,4701,1476],{"class":2500},[33,4703,517],{"class":46},[33,4705,87],{"class":86},[33,4707,90],{"class":57},[33,4709,465],{"class":46},[33,4711,140],{"class":57},[33,4713,143],{"class":50},[33,4715,146],{"class":57},[33,4717,810],{"class":46},[33,4719,4720,4722,4724,4726,4728,4730,4732],{"class":35,"line":778},[33,4721,465],{"class":46},[33,4723,51],{"class":50},[33,4725,54],{"class":46},[33,4727,3872],{"class":86},[33,4729,2717],{"class":86},[33,4731,2720],{"class":86},[33,4733,67],{"class":46},[33,4735,4736,4738,4740],{"class":35,"line":783},[33,4737,4688],{"class":792},[33,4739,4649],{"class":57},[33,4741,4742],{"class":39},"   # ✗ circular name reference (arr references itself)\n",[33,4744,4745],{"class":35,"line":789},[33,4746,4747],{"class":39},"# Fix: func() { local -n _ref=$1; echo \"${_ref[@]}\"; }\n",[33,4749,4750],{"class":35,"line":813},[33,4751,74],{"emptyLinePlaceholder":73},[33,4753,4754],{"class":35,"line":831},[33,4755,4756],{"class":39},"# ── Empty array with `set -u` (Bash \u003C 4.4) ──\n",[33,4758,4759,4762],{"class":35,"line":2597},[33,4760,4761],{"class":86},"set",[33,4763,4764],{"class":86}," -u\n",[33,4766,4767,4769,4771],{"class":35,"line":2602},[33,4768,465],{"class":46},[33,4770,51],{"class":50},[33,4772,3140],{"class":46},[33,4774,4775,4777,4779,4781,4783,4785,4787],{"class":35,"line":2623},[33,4776,87],{"class":86},[33,4778,90],{"class":57},[33,4780,465],{"class":46},[33,4782,140],{"class":57},[33,4784,143],{"class":50},[33,4786,146],{"class":57},[33,4788,4789],{"class":39},"   # Bash 4.4+: OK (empty). Bash \u003C 4.4: unbound variable error!\n",[33,4791,4792],{"class":35,"line":2628},[33,4793,4794],{"class":39},"# Fix: echo \"${arr[@]:-}\"\n",[15,4796,4798],{"id":4797},"quick-quiz","🧠 Quick Quiz",[4800,4801,4802],"p",{},"What does this print?",[20,4804,4805],{"language":22},[24,4806,4808],{"className":26,"code":4807,"language":22,"meta":28,"style":28},"arr=(\"a\" \"b\" \"c\")\narr[10]=\"d\"\necho \"count: ${#arr[@]}\"\necho \"indices: ${!arr[@]}\"\necho \"values: ${arr[@]}\"\n",[30,4809,4810,4827,4837,4854,4871],{"__ignoreMap":28},[33,4811,4812,4814,4816,4818,4820,4822,4825],{"class":35,"line":36},[33,4813,465],{"class":46},[33,4815,51],{"class":50},[33,4817,54],{"class":46},[33,4819,472],{"class":57},[33,4821,4595],{"class":57},[33,4823,4824],{"class":57}," \"c\"",[33,4826,67],{"class":46},[33,4828,4829,4832,4834],{"class":35,"line":43},[33,4830,4831],{"class":46},"arr[10]",[33,4833,51],{"class":50},[33,4835,4836],{"class":57},"\"d\"\n",[33,4838,4839,4841,4844,4846,4848,4850,4852],{"class":35,"line":70},[33,4840,87],{"class":86},[33,4842,4843],{"class":57}," \"count: ${",[33,4845,178],{"class":50},[33,4847,465],{"class":46},[33,4849,140],{"class":57},[33,4851,143],{"class":50},[33,4853,1322],{"class":57},[33,4855,4856,4858,4861,4863,4865,4867,4869],{"class":35,"line":77},[33,4857,87],{"class":86},[33,4859,4860],{"class":57}," \"indices: ${",[33,4862,274],{"class":50},[33,4864,465],{"class":46},[33,4866,140],{"class":57},[33,4868,143],{"class":50},[33,4870,1322],{"class":57},[33,4872,4873,4875,4878,4880,4882,4884],{"class":35,"line":83},[33,4874,87],{"class":86},[33,4876,4877],{"class":57}," \"values: ${",[33,4879,465],{"class":46},[33,4881,140],{"class":57},[33,4883,143],{"class":50},[33,4885,1322],{"class":57},[4887,4888,4889,4893,4901,4915,4921],"details",{},[4890,4891,4892],"summary",{},"Answer",[24,4894,4899],{"className":4895,"code":4897,"language":4898},[4896],"language-text","count: 4\nindices: 0 1 2 10\nvalues: a b c d\n","text",[30,4900,4897],{"__ignoreMap":28},[4800,4902,4903,4904,4907,4908,4911,4912,4914],{},"Bash arrays are ",[4905,4906,2951],"strong",{}," — you can assign to any index, and gaps don't count toward ",[30,4909,4910],{},"${#arr[@]}",". The count is the number of ",[4905,4913,4761],{}," elements, not the highest index + 1.",[4800,4916,4917,4920],{},[30,4918,4919],{},"${!arr[@]}"," shows the actual indices (0, 1, 2, 10) — there's a gap from 3 to 9.",[4800,4922,4923,4926,4927,4929,4930,4932],{},[4905,4924,4925],{},"The lesson",": Bash arrays are sparse hash maps (even indexed arrays). ",[30,4928,4910],{}," counts elements, not indices. Use ",[30,4931,4919],{}," to see the actual indices if you need contiguous access.",[4934,4935,4936],"style",{},"html pre.shiki code .sdCPZ, html code.shiki .sdCPZ{--shiki-default:#6A737D;--shiki-github-dark:#6A737D}html pre.shiki code .ssxIu, html code.shiki .ssxIu{--shiki-default:#24292E;--shiki-github-dark:#E1E4E8}html pre.shiki code .svdQ7, html code.shiki .svdQ7{--shiki-default:#D73A49;--shiki-github-dark:#F97583}html pre.shiki code .sJ6F3, html code.shiki .sJ6F3{--shiki-default:#032F62;--shiki-github-dark:#9ECBFF}html pre.shiki code .snvgF, html code.shiki .snvgF{--shiki-default:#005CC5;--shiki-github-dark:#79B8FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .github-dark .shiki span {color: var(--shiki-github-dark);background: var(--shiki-github-dark-bg);font-style: var(--shiki-github-dark-font-style);font-weight: var(--shiki-github-dark-font-weight);text-decoration: var(--shiki-github-dark-text-decoration);}html.github-dark .shiki span {color: var(--shiki-github-dark);background: var(--shiki-github-dark-bg);font-style: var(--shiki-github-dark-font-style);font-weight: var(--shiki-github-dark-font-weight);text-decoration: var(--shiki-github-dark-text-decoration);}html pre.shiki code .sIsaT, html code.shiki .sIsaT{--shiki-default:#6F42C1;--shiki-github-dark:#B392F0}html pre.shiki code .sCrzJ, html code.shiki .sCrzJ{--shiki-default:#E36209;--shiki-github-dark:#FFAB70}",{"title":28,"searchDepth":43,"depth":43,"links":4938},[4939,4940,4942,4943,4944,4945,4947,4948,4949,4950,4951,4952],{"id":17,"depth":43,"text":18},{"id":431,"depth":43,"text":4941},"[@] vs [*]: The Definitive Semantics",{"id":849,"depth":43,"text":850},{"id":1069,"depth":43,"text":1070},{"id":1428,"depth":43,"text":1429},{"id":1837,"depth":43,"text":4946},"mapfile \u002F readarray: Bulk Read Into Arrays",{"id":2217,"depth":43,"text":2218},{"id":2693,"depth":43,"text":2694},{"id":3085,"depth":43,"text":3086},{"id":3511,"depth":43,"text":3512},{"id":4263,"depth":43,"text":4264},{"id":4797,"depth":43,"text":4798},"Deep-dive into Bash array mechanics: indexed vs associative arrays, @ vs * expansion semantics, mapfile\u002Freadarray internals, sparse arrays, slicing, and production patterns for key-value stores and CSV processing. Code-first reference for senior engineers.","md",{},"\u002Fbash\u002F09-arrays",{"title":5,"description":4953},"bash\u002F09-arrays","o--ZEwKwNdrgRsppi4TlHojZLWe5mQY03VcC_JjRXbg",1789924644817]