Home > Enterprise >  Bash: How can I split a variable into two based on a substring?
Bash: How can I split a variable into two based on a substring?

Time:11-20

I would like to take a text representing a markdown string (from a GitHub PR comment) with a table in it: Title\n|Header|\n|:--|\n|Row1|\n|Row2]|

And split it into two variables, one up to and including the header row, and one holding everything after it, i.e.

HEAD=Title\n|Header|\n|:--|\n
BODY=|Row1|\n|Row2]|

I'd like to use a regex to identify if there is a header row, i.e. if it starts with |:- or |- for example.

CodePudding user response:

If the text contains literal newlines, then:

table=$'Title\n|Header|\n|:--|\n|Row1|\n|Row2]|'

Split into rows with

mapfile -t rows <<< "$table"

and

for ((idx=0; idx < ${#rows[@]}; idx  )); do
    [[ ${rows[idx]} =~ ^\|:?- ]] && break
done

join() {
    local IFS=$1
    shift
    echo "$*"
}

head=$( join $'\n' "${rows[@]:0:idx 1}" )
body=$( join $'\n' "${rows[@]:idx 1}" )

declare -p head body

outputs

declare -- head="Title
|Header|
|:--|"
declare -- body="|Row1|
|Row2]|"

If the text contains the 2-character string \n, then:

table='Title\n|Header|\n|:--|\n|Row1|\n|Row2]|'

Substitute the \n sequence with a single character and split into rows with read

IFS=$'\034' read -ra rows <<< "${table//\\n/$'\034'}"

and carry on from the for-loop above.

CodePudding user response:

#! /bin/bash

table=$'Title\n|Header|\n|:--|\n|Row1|\n|Row2]|'

if [[ "${table}" =~ \|: ]]; then
  H="|:"
else
  H="|-"
fi
BODY="${table#*${H}--|?}"
HEAD="${table%${BODY}}"

echo "BODY='${BODY}'" | cat -vet
echo "HEAD='${HEAD}'" | cat -vet

Output:

HEAD='Title$
|Header|$
|:--|$
'$
BODY='|Row1|$
|Row2]|'$
  • Related