Search code examples
windowsbatch-filecmdkeyvaluepair

How to loop through hard-coded key-value pairs line by line and parse each pair into key and value?


I am looking for a Windows Batch (Cmd.exe) counterpart of the Unix bash code shown below. Key-value pairs are given by HereDoc. The pairs are repeatedly read by the read command associated with the while command. IFS=$';' defines a semicolon (;) as the delimiter between the key and the value. The read command parses each pair into the variables ky and val. The loop body shall do something about the variables $ky and $val. Note that values may contain spaces.

while IFS=$';' read -r ky val; do
  # Do something about $ky and $val
  echo "$ky - $val"
done < <(cat << EOF
a;P p
b;Q q
c;R r
EOF
)
# OUTPUT
# a - P p
# b - Q q
# c - R r

The synopsis of the while-do-done compound command of bash is:

while ConditionalCommand; do COMMANDS; done

The command statement read -r ky val belongs to the ConditionalCommand of while.

The list of key-value pairs may be regarded as an associative list. However, there is no need to create an array, which would occupy memory in addition to the list.

On Cmd.exe, I thought about

for %%i in (
a;P p
b;Q q
c;R r
) do (
rem Parse each pair into two variables.
rem Do something about the two variables.
)

However, I do not know how to parse each pair, nor how to define the delimiter.

In fact, this batch code does not even work as I expected. I expected that this batch code would execute the loop body only three times, and that %%i would receive a whole pair (or an entire line) at a time. However, the loop body is actually executed nine times, and %%i receives only one letter at a time, as the following code reveals.

@echo off
setlocal enabledelayedexpansion

set n=1
for %%i in (
a;P p
b;Q q
c;R r
) do (
rem Parse each pair into two variables.
rem Do something about the two variables.
echo !n!
echo %%i
set /a n+=1
)

The answer by rojo to the question "Batch: Parse TXT Lines into Array" (questions/30403022) simulates an associative array. However, it uses an external file which contains key-value pairs. I do NOT want to use a file to provide key-value pairs. I want to hard-code key-value pairs. And that should be line by line; that is, a line for each pair. Hence, the list must consist of multiple lines. I do not want to lay the list on a single long line like

a;P pNLb;Q qNLc;R r    # <-- I do not want this

The answer by Aacini to the question "Find ALL Ocurences of Letter change to Diffrent Letter" (questions/35639223) uses an associative array. However, I do not need to create an array. Just a hard-coded associative list is enough for my application.


Solution

  • If the Key/Value pairs does not contain any of these character "?* then this will do what you want

    for %%P in (
        "a;P p"
        "b;Q q"
        "c;R r"
    ) do for /F "tokens=1* delims=;" %%A in ("%%~P") do (
        echo Key: %%A  ** Value: %%B
    )
    

    each Key/Value pair can be placed in a separate line as shown above or can be placed in one line. It's just a matter of taste, as long as the quoted pair are separated by at least one delimiter like ;,=<space><newLine> the FOR is happy.