In Shell, Split a Portion of a String with Dot as Delimiter

In shell, split a portion of a string with dot as delimiter

First, note that you don't use $ when assigning to a parameter in the shell. Your first line should be just this:

AU_NAME=AU_MSM3-3.7-00.01.02.03

The $ is used to get the value of the parameter once assigned. And the bit after the $ can be an expression in curly braces with extra stuff besides just the name, allowing you to perform various operations on the value. For example, you can do something like this:

IFS=. read major minor micro build <<EOF
${AU_NAME##*-}
EOF

where the ##*- strips off everything from the beginning of the string through the last '-', leaving just "00.01.02.03", and the IFS (Internal Field Separator) parameter tells the shell where to break the string into fields.

In bash, zsh, and ksh93+, you can get that onto one line by shortening the here-document to a here-string:

IFS=. read major minor micro build <<<"${AU_NAME##*-}"

More generally, in those same shells, you can split into an arbitrarily-sized array instead of distinct variables:

IFS=. components=(${AU_NAME##*-})

(Though that syntax won't work in especially-ancient versions of ksh; in them you have to do this instead:

IFS=. set -A components ${AU_NAME##*-}

)

That gets you this equivalence (except in zsh, which by default numbers the elements 1-4 instead of 0-3):

major=${components[0]}
minor=${components[1]}
micro=${components[2]}
build=${components[3]}

How do I split a string on a delimiter in Bash?

You can set the internal field separator (IFS) variable, and then let it parse into an array. When this happens in a command, then the assignment to IFS only takes place to that single command's environment (to read ). It then parses the input according to the IFS variable value into an array, which we can then iterate over.

This example will parse one line of items separated by ;, pushing it into an array:

IFS=';' read -ra ADDR <<< "$IN"
for i in "${ADDR[@]}"; do
# process "$i"
done

This other example is for processing the whole content of $IN, each time one line of input separated by ;:

while IFS=';' read -ra ADDR; do
for i in "${ADDR[@]}"; do
# process "$i"
done
done <<< "$IN"

How to split a string in shell and get the last field

You can use string operators:

$ foo=1:2:3:4:5
$ echo ${foo##*:}
5

This trims everything from the front until a ':', greedily.

${foo  <-- from variable foo
## <-- greedy front trim
* <-- matches anything
: <-- until the last ':'
}

How do I split a string on a delimiter in Bash?

You can set the internal field separator (IFS) variable, and then let it parse into an array. When this happens in a command, then the assignment to IFS only takes place to that single command's environment (to read ). It then parses the input according to the IFS variable value into an array, which we can then iterate over.

This example will parse one line of items separated by ;, pushing it into an array:

IFS=';' read -ra ADDR <<< "$IN"
for i in "${ADDR[@]}"; do
# process "$i"
done

This other example is for processing the whole content of $IN, each time one line of input separated by ;:

while IFS=';' read -ra ADDR; do
for i in "${ADDR[@]}"; do
# process "$i"
done
done <<< "$IN"

How to split the string with delimiter and swap the substring's position in bash?

Assumptions/understanding:

  • the objective is to rename the files (the question mentions Goal is to name them as ... but there is no mention of the mv command ... ???)
  • all file names contain a single period
  • we want to switch the before-period/after-period portions of the file names to create new file names
  • no files exist with the new file name (eg, we don't currently have files named a.txt and txt.a)

One idea using parameter expansion which allows us to eliminate the overhead of sub-process calls:

for fname in *.txt
do
new_fname="${fname#*.}.${fname%.*}"
echo mv "${fname}" "${new_fname}"
done

For files names a.txt, b.txt and c.txt this generates:

mv a.txt txt.a
mv b.txt txt.b
mv c.txt txt.c

Once OP is satisfied with the results the echo can be removed and the script should perform the actual mv/rename.

split based on the last dot and create a new column with the last part of the string

You may use this sed:

sed -E 's/^([[:blank:]]*[^[:blank:]]+)\.([^[:blank:]]+)/\1 \2/' file

5_8S_A.3-C_1 A 50
6_FS_B.L.3-O_1 A 20
H.YU-201 D 80
UI-LP.56.2011 A 10

Details:

  • ^: Start
  • ([[:blank:]]*[^[:blank:]]+): Capture group #2 to match 0 or more whitespaces followed by 1+ non-whitespace characters.
  • \.: Match a dot. Since this regex pattern is greedy it will match until last dot
  • ([^[:blank:]]+): Capture group #2 to match 1+ non-whitespace characters
  • \1 \2: Replacement to place a space between capture value #1 and capture value #2

Extract substring before dot

You need to use %% to remove the longest match from the end:

$ echo "${s%%.*}"
4

From the docs:

${parameter%%word}
Remove Largest Suffix Pattern. The word shall be expanded to produce a pattern. The parameter expansion shall then result in parameter, with the largest portion of the suffix matched by the pattern deleted.



Related Topics



Leave a reply



Submit