Never been to CodeSnippets before?

Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world (or not, you can keep them private!)

Splitting strings in Bash

Inspired by how split a string in bash? and BASH: Split a string without 'cut' or 'awk'.


function split() {

   declare DELIM printstr reststr str

   if [[ "${1}" == '-d' ]] && [[ $# -ge 2 ]]; then
      DELIM="${2}"
      shift 2
   else
      DELIM=" "
   fi

   # if /dev/stdin has a size greater than zero ...
   if [[ -s /dev/stdin ]]; then 
      str="$(</dev/stdin)"
   else 
      str="${@}"
   fi 

   while [[ -n "$str" ]]; do
      reststr="${str#*${DELIM}}"
      [[ "${str}" == "${reststr}" ]] && printf "%s\n" "${str}" && return 0
      #[[ "${str}" == "${reststr}" ]] && printf "%s\n" "${str}" && break
      #[[ "${str}" == "${reststr}" ]] && printf "%s\n" "${str}" && str="" && continue
      printstr="${str%%${DELIM}*}"
      [[ -n "${printstr}" ]] && printf "%s\n" "${printstr}"
      str="${reststr}"
   done

   return 0

}


split -d a bdsdaaadfeeee
echo bdsdaaadfeeee | split -d a

split -d a " bd sdaaadfe eee "
echo " bd sdaaadfe eee " | split -d a

split -d aa " bd sdaaadfe eee "
echo " bd sdaaadfe eee " | split -d aa

split -d aaa " bd sdaaadfe eee "
echo " bd sdaaadfe eee " | split -d aaa



#----------------------------------------------------------------------



function split0() {

   declare DELIM printstr reststr str

   if [[ "${1}" == '-d' ]] && [[ $# -ge 2 ]]; then
      DELIM="${2}"
      shift 2
   else
      DELIM=" "
   fi

   # if /dev/stdin has a size greater than zero ...
   if [[ -s /dev/stdin ]]; then 
      str="$(</dev/stdin)"
   else 
      str="${@}"
   fi 

   while [[ -n "$str" ]]; do
      reststr="${str#*${DELIM}}"
      [[ "${str}" == "${reststr}" ]] && printf "%s\000" "${str}" && return 0
      #[[ "${str}" == "${reststr}" ]] && printf "%s\000" "${str}" && break
      #[[ "${str}" == "${reststr}" ]] && printf "%s\000" "${str}" && str="" && continue
      printstr="${str%%${DELIM}*}"
      [[ -n "${printstr}" ]] && printf "%s\000" "${printstr}"
      str="${reststr}"
   done

   return 0

}


split0 -d a bdsdaaadfeeee | xargs -0 
split0 -d a bdsdaaadfeeee | xargs -0 echo
split0 -d a bdsdaaadfeeee | xargs -0 printf "%s\n"

echo bdsdaaadfeeee | split0 -d a | xargs -0


split0 -d a " bd sdaaadfe eee " | xargs -0 printf "%s\n"
echo " bd sdaaadfe eee " | split0 -d a | xargs -0 printf "%s\n"

split0 -d aa " bd sdaaadfe eee " | xargs -0 printf "%s\n"
echo " bd sdaaadfe eee " | split0 -d aa | xargs -0 printf "%s\n"

split0 -d aaa " bd sdaaadfe eee " | xargs -0 printf "%s\n"
echo " bd sdaaadfe eee " | split0 -d aaa | xargs -0 printf "%s\n"

Debugging a file name with a backslash character in Bash

# create a file name containing a backslash character \
file=${HOME}/Desktop/'te:st\file'.txt
echo "${file}"
echo "${file}" | sed -n -e 'l'

echo 'This is a test case for a file name containing a backslash \ character!' > "${file}"
open -e "${file}"

set -vx

# note: avoid trailing spaces in ed commands
cat <<EOF | /bin/ed -s "${file}"
H
,g|^This|s|test case|SUCCESSFUL TEST CASE|
w
EOF

open -e "${file}"


# escape backslashes
cat <<EOF | /bin/ed -s "${file//\\/\\\\}"
H
,g|^This|s|test case|SUCCESSFUL TEST CASE|
w
EOF

open -e "${file}"


# printf "%q"
help printf | sed -E "s/(%q)/$(printf '\e[1m\\1\e[m')/"
echo "${file}"
echo "$(printf "%q" "${file}")"   # cf. help printf
echo "$(printf "%q" "${file}")" | sed -n -e 'l'

# escape file name
cat <<EOF | /bin/ed -s "$(printf "%q" "${file}")"
H
,g|^This|s|backslash|BACKSLASH|
w
EOF

open -e "${file}"


echo "${file}"
echo "${file}" | sed -n -e 'l'

file="${file//\\/\\\\}"
echo "${file}"
echo "${file}" | sed -n -e 'l'


# references
man bash 2>/dev/null | less -p 'backslash'
man bash 2>/dev/null | less -p 'Each command in a pipeline'
man bash 2>/dev/null | less -p 'Functions are executed'
help printf | sed -E "s/(%q)/$(printf '\e[1m\\1\e[m')/"
open http://en.wikipedia.org/wiki/Filename


# "Each command in a pipeline is executed as a separate process (i.e., in a subshell)."
# From: man bash

# "Functions are executed in the context of the current shell; no new process is created to 
# interpret  them (contrast this with the execution of a shell script)."
# From: man bash

# "Unix-like systems are an exception, as the only control character forbidden in file names 
# is the null character, as that's the end-of-string indicator in C. Trivially, Unix also 
# excludes the path separator / from appearing in filenames."
# From: http://en.wikipedia.org/wiki/Filename