Score:0

How do you reassign a positional argument so that it is available outside of the function?

us flag

I'm trying to create a #!/bin/sh compatible string_split function that has a similar command syntax to the read command so that you can pass in the string you want to split and the variables you want to assign the strings too.

This is the function I've come up with, but I can't figure out how to make the new values available outside of the function like the read command can.

#!/bin/sh
split_str() {
    input_original=$1
    input=$1
    input_delimiter=$2

    input=$(echo "$input" | sed -e "s/$input_delimiter/ /g")
    set -- "$input_original" "$input_delimiter" $input
}

The desired command use would look like this:

split_str "Hello World" " " word1 word2
echo "$word1"
# Output: Hello
echo "$word2"
# Output: World

Solution

Using bac0ns answer below I was able to get this solution which works with any number of output parameters passed. Thanks for the help @bac0n

#!/bin/sh
split_str() {
    input=$1
    input_delimiter=$2
    
    # Isolate the output parameters
    output_params=$(echo "${@}" | sed -e "s/$input $input_delimiter//g")

    # Add an extra variable argument to catch any overflow.
    # This prevents any extra parts of the sub string from being added to the
    # passed parameters. 
    output_params="$output_params overflow"

    # Split the string by reading the values in with read
    IFS="$input_delimiter" read -r $output_params << EOF
$1
EOF
}
kevincorrigan avatar
us flag
@Terrance Can you expand on that? If I add return $input to my function I get an error. "numeric argument required"
Terrance avatar
id flag
Sorry about that, I use that to return a 0 or 1 when I am calling my functions if they are true or false.
bac0n avatar
cn flag
is /bin/sh (dash) a requirement?
kevincorrigan avatar
us flag
@bac0n Yes /bin/sh is required.
Score:2
cn flag

Functions run in the same context as the current shell, it's perfectly fine to set word1 and word2 inside the function and use them from the calling scope:

split(){
    local a=$1 b=$2
    shift 2
    IFS=$b read -r $@ _ << \
EOF
    $a
EOF
}

split "hello world" " " word1 word2

printf %s\\n "1:$word1" "2:$word2"
kevincorrigan avatar
us flag
Thank you! This wasn't exactly what I needed but it pointed me in the right direction. I'll update my question with my new function.
mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.