如何在bash中的定界线上拆分字符串?

发布于 2025-02-09 06:43:46 字数 2266 浏览 2 评论 0 原文

我将此字符串存储在一个变量中:

IN="[email protected];[email protected]"

现在,我想通过; 定界符将字符串拆分,以便我有:

ADDR1="[email protected]"
ADDR2="[email protected]"

我不一定需要 addr1 addr2 变量。如果它们是阵列的元素,那就更好了。


在下面的答案中提出了建议之后,我最终得到了以下内容,这就是我所追求的:

#!/usr/bin/env bash

IN="[email protected];[email protected]"

mails=$(echo $IN | tr ";" "\n")

for addr in $mails
do
    echo "> [$addr]"
done

输出:

> [[email protected]]
> [[email protected]]

有一个解决方案涉及设置 internal_field_separator (ifs)to ; 。我不确定该答案发生了什么,您如何重置返回默认值?

我保留旧的 ifs ,然后还原:

IN="[email protected];[email protected]"

OIFS=$IFS
IFS=';'
mails2=$IN
for x in $mails2
do
    echo "> [$x]"
done

IFS=$OIFS

btw,当我尝试

mails2=($IN)

回复: ifs 解决方案,我尝试了此操作,然后它起作用, 在循环中,中的 $ $ nther tragets n n ockets in 它有效。

I have this string stored in a variable:

IN="[email protected];[email protected]"

Now I would like to split the strings by ; delimiter so that I have:

ADDR1="[email protected]"
ADDR2="[email protected]"

I don't necessarily need the ADDR1 and ADDR2 variables. If they are elements of an array that's even better.


After suggestions from the answers below, I ended up with the following which is what I was after:

#!/usr/bin/env bash

IN="[email protected];[email protected]"

mails=$(echo $IN | tr ";" "\n")

for addr in $mails
do
    echo "> [$addr]"
done

Output:

> [[email protected]]
> [[email protected]]

There was a solution involving setting Internal_field_separator (IFS) to ;. I am not sure what happened with that answer, how do you reset IFS back to default?

RE: IFS solution, I tried this and it works, I keep the old IFS and then restore it:

IN="[email protected];[email protected]"

OIFS=$IFS
IFS=';'
mails2=$IN
for x in $mails2
do
    echo "> [$x]"
done

IFS=$OIFS

BTW, when I tried

mails2=($IN)

I only got the first string when printing it in loop, without brackets around $IN it works.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(30

往昔成烟 2025-02-16 06:43:47

除了已经提供的奇妙答案之外,如果只是打印出您可能考虑使用 awk 的数据问题:

awk -F";" '{for (i=1;i<=NF;i++) printf("> [%s]\n", $i)}' <<< "$IN"

这将字段分隔符设置为; ,所以它可以使用循环的循环循环并相应打印。

测试:

$ IN="[email protected];[email protected]"
$ awk -F";" '{for (i=1;i<=NF;i++) printf("> [%s]\n", $i)}' <<< "$IN"
> [[email protected]]
> [[email protected]]

用另一个输入

$ awk -F";" '{for (i=1;i<=NF;i++) printf("> [%s]\n", $i)}' <<< "a;b;c   d;e_;f"
> [a]
> [b]
> [c   d]
> [e_]
> [f]

Apart from the fantastic answers that were already provided, if it is just a matter of printing out the data you may consider using awk:

awk -F";" '{for (i=1;i<=NF;i++) printf("> [%s]\n", $i)}' <<< "$IN"

This sets the field separator to ;, so that it can loop through the fields with a for loop and print accordingly.

Test

$ IN="[email protected];[email protected]"
$ awk -F";" '{for (i=1;i<=NF;i++) printf("> [%s]\n", $i)}' <<< "$IN"
> [[email protected]]
> [[email protected]]

With another input:

$ awk -F";" '{for (i=1;i<=NF;i++) printf("> [%s]\n", $i)}' <<< "a;b;c   d;e_;f"
> [a]
> [b]
> [c   d]
> [e_]
> [f]
手心的温暖 2025-02-16 06:43:47
IN="[email protected];[email protected]"
IFS=';'
read -a IN_arr <<< "${IN}"
for entry in "${IN_arr[@]}"
do
    echo $entry
done

输出

[email protected]
[email protected]

系统:Ubuntu 12.04.1

IN="[email protected];[email protected]"
IFS=';'
read -a IN_arr <<< "${IN}"
for entry in "${IN_arr[@]}"
do
    echo $entry
done

Output

[email protected]
[email protected]

System : Ubuntu 12.04.1

青衫负雪 2025-02-16 06:43:47

使用 set 内置来加载 $@数组:

IN="[email protected];[email protected]"
IFS=';'; set $IN; IFS=

然后,让派对开始:

echo $#
for a; do echo $a; done
ADDR1=$1 ADDR2=$2
\t\n'

然后,让派对开始:


Use the set built-in to load up the $@ array:

IN="[email protected];[email protected]"
IFS=';'; set $IN; IFS=

Then, let the party begin:

echo $#
for a; do echo $a; done
ADDR1=$1 ADDR2=$2
\t\n'

Then, let the party begin:



    
饮惑 2025-02-16 06:43:47

两个都不需要bash数组的bournis替代方案:

案例1 :保持良好而简单:将newline用作记录分离器...例如。

IN="[email protected]
[email protected]"

while read i; do
  # process "$i" ... eg.
    echo "[email:$i]"
done <<< "$IN"

注意:在第一种情况下,没有任何子过程可以协助列表操纵。

想法:也许值得广泛使用NL内部,并且仅在生成最终结果外部时才转换为不同的rs。

案例2 :使用“”;作为记录分离器...例如。

NL="
" IRS=";" ORS=";"

conv_IRS() {
  exec tr "$1" "$NL"
}

conv_ORS() {
  exec tr "$NL" "$1"
}

IN="[email protected];[email protected]"
IN="$(conv_IRS ";" <<< "$IN")"

while read i; do
  # process "$i" ... eg.
    echo -n "[email:$i]$ORS"
done <<< "$IN"

在这两种情况下,在循环完成后,可以在循环内组成一个子列表。当操作内存中的列表时,这很有用,而是将列表存储在文件中。 {PS保持冷静并继续B-)}}}

Two bourne-ish alternatives where neither require bash arrays:

Case 1: Keep it nice and simple: Use a NewLine as the Record-Separator... eg.

IN="[email protected]
[email protected]"

while read i; do
  # process "$i" ... eg.
    echo "[email:$i]"
done <<< "$IN"

Note: in this first case no sub-process is forked to assist with list manipulation.

Idea: Maybe it is worth using NL extensively internally, and only converting to a different RS when generating the final result externally.

Case 2: Using a ";" as a record separator... eg.

NL="
" IRS=";" ORS=";"

conv_IRS() {
  exec tr "$1" "$NL"
}

conv_ORS() {
  exec tr "$NL" "$1"
}

IN="[email protected];[email protected]"
IN="$(conv_IRS ";" <<< "$IN")"

while read i; do
  # process "$i" ... eg.
    echo -n "[email:$i]$ORS"
done <<< "$IN"

In both cases a sub-list can be composed within the loop is persistent after the loop has completed. This is useful when manipulating lists in memory, instead storing lists in files. {p.s. keep calm and carry on B-) }

失退 2025-02-16 06:43:47

在Android Shell中,大多数提出的方法无效:

$ IFS=':' read -ra ADDR <<<"$PATH"                             
/system/bin/sh: can't create temporary file /sqlite_stmt_journals/mksh.EbNoR10629: No such file or directory

有效的是:

$ for i in ${PATH//:/ }; do echo $i; done
/sbin
/vendor/bin
/system/sbin
/system/bin
/system/xbin

其中 // 表示全局替换。

In Android shell, most of the proposed methods just do not work:

$ IFS=':' read -ra ADDR <<<"$PATH"                             
/system/bin/sh: can't create temporary file /sqlite_stmt_journals/mksh.EbNoR10629: No such file or directory

What does work is:

$ for i in ${PATH//:/ }; do echo $i; done
/sbin
/vendor/bin
/system/sbin
/system/bin
/system/xbin

where // means global replacement.

腹黑女流氓 2025-02-16 06:43:47
IN='[email protected];[email protected];Charlie Brown <[email protected];!"#$%&/()[]{}*? are no problem;simple is beautiful :-)'
set -f
oldifs="$IFS"
IFS=';'; arrayIN=($IN)
IFS="$oldifs"
for i in "${arrayIN[@]}"; do
echo "$i"
done
set +f

输出:

[email protected]
[email protected]
Charlie Brown <[email protected]
!"#$%&/()[]{}*? are no problem
simple is beautiful :-)

说明:使用括号()的简单分配转换为半分离的列表,只要您在执行此操作时就具有正确的IF。循环的标准像往常一样处理该数组中的单个项目。
请注意,在变量中给出的列表必须“难”,即带有单个tick。

必须保存和恢复IF,因为Bash不会以命令与命令相同的方式对待作业。另一种解决方法是将分配包装在功能中,并使用修改的IF调用该函数。在这种情况下,不需要单独保存/还原IF。感谢您指出的“ Bize”。

IN='[email protected];[email protected];Charlie Brown <[email protected];!"#$%&/()[]{}*? are no problem;simple is beautiful :-)'
set -f
oldifs="$IFS"
IFS=';'; arrayIN=($IN)
IFS="$oldifs"
for i in "${arrayIN[@]}"; do
echo "$i"
done
set +f

Output:

[email protected]
[email protected]
Charlie Brown <[email protected]
!"#$%&/()[]{}*? are no problem
simple is beautiful :-)

Explanation: Simple assignment using parenthesis () converts semicolon separated list into an array provided you have correct IFS while doing that. Standard FOR loop handles individual items in that array as usual.
Notice that the list given for IN variable must be "hard" quoted, that is, with single ticks.

IFS must be saved and restored since Bash does not treat an assignment the same way as a command. An alternate workaround is to wrap the assignment inside a function and call that function with a modified IFS. In that case separate saving/restoring of IFS is not needed. Thanks for "Bize" for pointing that out.

末蓝 2025-02-16 06:43:47

这是我的答案!

DELIMITER_VAL='='

read -d '' F_ABOUT_DISTRO_R <<"EOF"
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=14.04
DISTRIB_CODENAME=trusty
DISTRIB_DESCRIPTION="Ubuntu 14.04.4 LTS"
NAME="Ubuntu"
VERSION="14.04.4 LTS, Trusty Tahr"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 14.04.4 LTS"
VERSION_ID="14.04"
HOME_URL="http://www.ubuntu.com/"
SUPPORT_URL="http://help.ubuntu.com/"
BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"
EOF

SPLIT_NOW=$(awk -F$DELIMITER_VAL '{for(i=1;i<=NF;i++){printf "%s\n", $i}}' <<<"${F_ABOUT_DISTRO_R}")
while read -r line; do
   SPLIT+=("$line")
done <<< "$SPLIT_NOW"
for i in "${SPLIT[@]}"; do
    echo "$i"
done

为什么这种方法对我来说是“最好的”?

由于两个原因:

  1. 不需要逃脱定界符;
  2. 空白空间您将不会有问题。该值将在数组中正确分开。

Here's my answer!

DELIMITER_VAL='='

read -d '' F_ABOUT_DISTRO_R <<"EOF"
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=14.04
DISTRIB_CODENAME=trusty
DISTRIB_DESCRIPTION="Ubuntu 14.04.4 LTS"
NAME="Ubuntu"
VERSION="14.04.4 LTS, Trusty Tahr"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 14.04.4 LTS"
VERSION_ID="14.04"
HOME_URL="http://www.ubuntu.com/"
SUPPORT_URL="http://help.ubuntu.com/"
BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"
EOF

SPLIT_NOW=$(awk -F$DELIMITER_VAL '{for(i=1;i<=NF;i++){printf "%s\n", $i}}' <<<"${F_ABOUT_DISTRO_R}")
while read -r line; do
   SPLIT+=("$line")
done <<< "$SPLIT_NOW"
for i in "${SPLIT[@]}"; do
    echo "$i"
done

Why this approach is "the best" for me?

Because of two reasons:

  1. You do not need to escape the delimiter;
  2. You will not have problem with blank spaces. The value will be properly separated in the array.
原来分手还会想你 2025-02-16 06:43:46

您可以设置内部字段分隔仪(ifs)变量,然后将其分析成一个数组。当这种情况发生在命令中时,将分配给 ifs 仅发生到该单个命令的环境( read )。然后,它根据 ifs 变量值将输入解析为一个数组,然后我们可以迭代。

此示例将解析一行由; 分开的项目,将其推入数组:

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

另一个示例是处理中的 $的整个内容,每次输入由; 分开:

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

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"
与君绝 2025-02-16 06:43:46

取自

IN="[email protected];[email protected]"
arrIN=(${IN//;/ })
echo ${arrIN[1]}                  # Output: [email protected]

说明:

此构造替换了';'的所有出现(初始 // 表示全局替换) >在中使用'''(单个空间),然后将空格删除的字符串解释为数组(这就是周围的括号所做的)。

''字符替换每个''字符的语法用来替换每个';'字符

有一些常见的陷阱:

  1. 如果原始字符串有空间,则需要使用 ifs
  • ifs =':':'; arrin =($ in);未设置IFS;
  1. 如果原始字符串具有空格,定界符是新行,则可以设置 with:
  • ifs = $'\ n'; arrin =($ in);未设置IF;

Taken from Bash shell script split array:

IN="[email protected];[email protected]"
arrIN=(${IN//;/ })
echo ${arrIN[1]}                  # Output: [email protected]

Explanation:

This construction replaces all occurrences of ';' (the initial // means global replace) in the string IN with ' ' (a single space), then interprets the space-delimited string as an array (that's what the surrounding parentheses do).

The syntax used inside of the curly braces to replace each ';' character with a ' ' character is called Parameter Expansion.

There are some common gotchas:

  1. If the original string has spaces, you will need to use IFS:
  • IFS=':'; arrIN=($IN); unset IFS;
  1. If the original string has spaces and the delimiter is a new line, you can set IFS with:
  • IFS=$'\n'; arrIN=($IN); unset IFS;
清风夜微凉 2025-02-16 06:43:46

我已经看到了一些参考剪切命令的答案,但它们都已删除。没有人对此进行详细说明,这有点奇怪,因为我认为这是做这种类型的事情的最有用的命令之一,尤其是用于解析界限日志文件。

如果将这个特定示例分为bash脚本数组, tr 可能更有效,但是 cut> cut 可以使用,如果要拉出特定的特定中间的字段。

示例:

$ echo "[email protected];[email protected]" | cut -d ";" -f 1
[email protected]
$ echo "[email protected];[email protected]" | cut -d ";" -f 2
[email protected]

您显然可以将其放入循环中,并迭代 -f 参数以独立拉动每个字段。

当您拥有具有这样的行的界限日志文件时,这将变得更有用:

2015-04-27|12345|some action|an attribute|meta data

剪切能够 cat 此文件并选择一个特定字段以进行进一步处理。

I've seen a couple of answers referencing the cut command, but they've all been deleted. It's a little odd that nobody has elaborated on that, because I think it's one of the more useful commands for doing this type of thing, especially for parsing delimited log files.

In the case of splitting this specific example into a bash script array, tr is probably more efficient, but cut can be used, and is more effective if you want to pull specific fields from the middle.

Example:

$ echo "[email protected];[email protected]" | cut -d ";" -f 1
[email protected]
$ echo "[email protected];[email protected]" | cut -d ";" -f 2
[email protected]

You can obviously put that into a loop, and iterate the -f parameter to pull each field independently.

This gets more useful when you have a delimited log file with rows like this:

2015-04-27|12345|some action|an attribute|meta data

cut is very handy to be able to cat this file and select a particular field for further processing.

£冰雨忧蓝° 2025-02-16 06:43:46

如果您不介意立即处理它们,我喜欢这样做:

for i in $(echo $IN | tr ";" "\n")
do
  # process
done

您可以使用这种循环来初始化数组,但是可能有一种更简单的方法可以做到这一点。

If you don't mind processing them immediately, I like to do this:

for i in $(echo $IN | tr ";" "\n")
do
  # process
done

You could use this kind of loop to initialize an array, but there's probably an easier way to do it.

寒冷纷飞旳雪 2025-02-16 06:43:46

兼容答案

有很多不同的方法可以在 bash

但是,必须首先注意到 bash 具有许多特别功能(So-called bashisms )在任何其他 shell

特别是, arrays cossotiative数组模式替换,这些 在本文中的解决方案中以及线程中的其他使用中使用,是 bashisms ,可能在许多人使用的其他 shells 下无法使用。

例如:在我的 debian gnu/linux 上,有一个标准 shell称为 dash ;我知道很多人喜欢使用另一个称为 ksh ;还有一个特殊工具,称为 busybox 带有他自己的shell Insteller( ash )。

for posix shell < /a>兼容答案,转到本答案的最后一部分!

请求的字符串

在上面的问题中要分开的字符串是:

IN="[email protected];[email protected]"

我将使用此字符串的修改版本来确保我的解决方案对包含whitespace的字符串具有强大的功能,这可能会破坏其他解决方案:

IN="[email protected];[email protected];Full Name <[email protected]>"

基于 bash (版本&gt; = 4.2)

pure bash 中,我们可以创建An array ,其元素由 ifs em>(输入字段分离器)。 IFS除其他外,告诉 bash 在定义数组时应将其视为元素之间的分界符:

IN="[email protected];[email protected];Full Name <[email protected]>"

# save original IFS value so we can restore it later
oIFS="$IFS"
IFS=";"
declare -a fields=($IN)
IFS="$oIFS"
unset oIFS

bash 的较新版本中使用IFS定义更改该命令的IFS,然后将其重置为以前的值。这意味着我们只需一行即可完成以上操作:

IFS=\; read -ra fields <<<"$IN"
# after this command, the IFS resets back to its previous value (here, the default):
set | grep ^IFS=
# IFS=

我们可以看到,中的字符串已存储在名为 fields 的数组中,在半olons上分开:(

set | grep ^fields=\\\|^IN=
# fields=([0]="[email protected]" [1]="[email protected]" [2]="Full Name <[email protected]>")
# IN='[email protected];[email protected];Full Name <[email protected]>'

我们可以还使用声明-p :)

declare -p IN fields
# declare -- IN="[email protected];[email protected];Full Name <[email protected]>"
# declare -a fields=([0]="[email protected]" [1]="[email protected]" [2]="Full Name <[email protected]>")

请注意,读取最快进行分割的方法,因为没有< em> forks 或调用外部资源。

定义数组后,您可以使用一个简单的循环来处理每个字段(或者,您现在定义的数组中的每个元素):

# `"${fields[@]}"` expands to return every element of `fields` array as a separate argument
for x in "${fields[@]}" ;do
    echo "> [$x]"
    done
# > [[email protected]]
# > [[email protected]]
# > [Full Name <[email protected]>]

或者可以在使用移动后处理后从数组中删除每个字段方法,我喜欢的方法:

while [ "$fields" ] ;do
    echo "> [$fields]"
    # slice the array 
    fields=("${fields[@]:1}")
    done
# > [[email protected]]
# > [[email protected]]
# > [Full Name <[email protected]>]

如果您只想简单地打印数组,您甚至不需要循环浏览它:

printf "> [%s]\n" "${fields[@]}"
# > [[email protected]]
# > [[email protected]]
# > [Full Name <[email protected]>]

更新:最近 bash &gt; = 4.4

bash 的较新版本中,您也可以使用命令 mapfile

mapfile -td \; fields < <(printf "%s\0" "$IN")

此语法保留特殊的chars ,新线和空字段!

如果您不想包含空字段,则可以执行以下操作:

mapfile -td \; fields <<<"$IN"
fields[-1]=${fields[-1]%

使用 mapfile ,您还可以跳过划界元素上声明数组并隐式“循环”,每个元素都在每个元素上调用一个函数:

myPubliMail() {
    printf "Seq: %6d: Sending mail to '%s'..." $1 "$2"
    # mail -s "This is not a spam..." "$2" </path/to/body
    printf "\e[3D, done.\n"
}

mapfile < <(printf "%s\0" "$IN") -td \; -c 1 -C myPubliMail

(注意:格式字符串末端的 \ 0 ,如果您不在字符串末端关心空字段,或者它们不存在。)

mapfile < <(echo -n "$IN") -td \; -c 1 -C myPubliMail

# Seq:      0: Sending mail to '[email protected]', done.
# Seq:      1: Sending mail to '[email protected]', done.
# Seq:      2: Sending mail to 'Full Name <[email protected]>', done.

但是您甚至可以使用 newline (mapfile的默认值)分隔符:

mapfile <<<"${IN//;/

您可以使用&lt;&lt;&lt;&lt; ,并且在功能中包括一些处理,以删除newline IT添加:

myPubliMail() {
    local seq=$1 dest="${2%

基于 shell

如果您不能使用 bash 或如果您想编写可以在许多不同的外壳中使用的东西,那么您经常 use bashisms - 这包括我们在上述解决方案中使用的数组。

但是,我们不需要使用数组来循环浏览字符串的“元素”。许多壳中使用了一种语法,用于从 first 最后一个中删除字符串的子字符串。请注意,*是一个代表零或更多字符的通配符:(

,在任何解决方案中缺乏此方法是我写这个答案的主要原因;)

${var#*SubStr}  # drops substring from start of string up to first occurrence of `SubStr`
${var##*SubStr} # drops substring from start of string up to last occurrence of `SubStr`
${var%SubStr*}  # drops substring from last occurrence of `SubStr` to end of string
${var%%SubStr*} # drops substring from first occurrence of `SubStr` to end of string

到目前为止 href =“ https://stackoverflow.com/posts/comments/47972612?noredirect=1”> score_under :

分别从字符串的 start end 中删除最短的匹配子字符串,和

## %% 删除最长可能的匹配子字符串。

使用上述语法,我们可以创建一种方法,通过在定界符之前或之后删除子字符串,从字符串中提取子字符串“元素”。

下面的代码块在 bash (包括mac os的 bash ), dash ksh yash> yash << /a>, zsh busybox 's ash :(

感谢 adam katz '使此循环变得更简单!)

IN="[email protected];[email protected];Full Name <[email protected]>"
while [ "$IN" != "$iter" ] ;do
    # extract the substring from start of string up to delimiter.
    iter=${IN%%;*}
    # delete this first "element" AND his separator, from $IN.
    IN="${IN#$iter;}"
    # Print (or doing anything with) the first "element".
    printf '> [%s]\n' "$iter"
done
# > [[email protected]]
# > [[email protected]]
# > [Full Name <[email protected]>]

为什么不剪切

剪切对于在大文件中提取列很有用,但是 forks 重复( var = $(echo ... | cut ... cut ...) )迅速过度杀伤!

这是一个正确的语法,在许多 posix shell 使用剪切,如 dougw << /a>:

IN="[email protected];[email protected];Full Name <[email protected]>"
i=1
while iter=$(echo "$IN"|cut -d\; -f$i) ; [ -n "$iter" ] ;do
    printf '> [%s]\n' "$iter"
    i=$((i+1))
done

比较执行时间

splitByCut() {
    local i=1
    while iter=$(echo "$1"|cut -d\; -f$i) ; [ -n "$iter" ] ;do
        printf '> [%s]\n' "$iter"
        i=$((i+1))
    done
}

splitByMapFile() {
    iterMF() {
        local seq=$1 dest="${2%

准备999个字段:

IN="[email protected];[email protected];Full Name <[email protected]>"
printf -v in40 %333s
in40=${in40// /$IN;}
in40=${in40%;}

然后

start=${EPOCHREALTIME/.};splitByMapFile "$in40" |
    md5sum;elap=00000$((${EPOCHREALTIME/.}-start))
printf 'Elapsed: %.4f secs.\n' ${elap::-6}.${elap: -6}
e35655f2a7fa367144a31f72f55e4dc0  -
Elapsed: 0.0454 secs.

start=${EPOCHREALTIME/.};splitByCut "$in40" |
    md5sum;elap=00000$((${EPOCHREALTIME/.}-start))
printf 'Elapsed: %.4f secs.\n' ${elap::-6}.${elap: -6}
e35655f2a7fa367144a31f72f55e4dc0  -
Elapsed: 2.2212 secs.

使用 1 forks cut by field 1 forks >,对于少于1'000字段

\t\n'

我们可以看到,中的字符串已存储在名为 fields 的数组中,在半olons上分开:(


我们可以还使用声明-p :)


请注意,读取最快进行分割的方法,因为没有< em> forks 或调用外部资源。

定义数组后,您可以使用一个简单的循环来处理每个字段(或者,您现在定义的数组中的每个元素):


或者可以在使用移动后处理后从数组中删除每个字段方法,我喜欢的方法:


如果您只想简单地打印数组,您甚至不需要循环浏览它:


更新:最近 bash &gt; = 4.4

bash 的较新版本中,您也可以使用命令 mapfile


此语法保留特殊的chars ,新线和空字段!

如果您不想包含空字段,则可以执行以下操作:


使用 mapfile ,您还可以跳过划界元素上声明数组并隐式“循环”,每个元素都在每个元素上调用一个函数:


(注意:格式字符串末端的 \ 0 ,如果您不在字符串末端关心空字段,或者它们不存在。)


但是您甚至可以使用 newline (mapfile的默认值)分隔符:


您可以使用&lt;&lt;&lt;&lt; ,并且在功能中包括一些处理,以删除newline IT添加:


基于 shell

如果您不能使用 bash 或如果您想编写可以在许多不同的外壳中使用的东西,那么您经常 use bashisms - 这包括我们在上述解决方案中使用的数组。

但是,我们不需要使用数组来循环浏览字符串的“元素”。许多壳中使用了一种语法,用于从 first 最后一个中删除字符串的子字符串。请注意,*是一个代表零或更多字符的通配符:(

,在任何解决方案中缺乏此方法是我写这个答案的主要原因;)


到目前为止 href =“ https://stackoverflow.com/posts/comments/47972612?noredirect=1”> score_under :

分别从字符串的 start end 中删除最短的匹配子字符串,和

## %% 删除最长可能的匹配子字符串。

使用上述语法,我们可以创建一种方法,通过在定界符之前或之后删除子字符串,从字符串中提取子字符串“元素”。

下面的代码块在 bash (包括mac os的 bash ), dash ksh yash> yash << /a>, zsh busybox 's ash :(

感谢 adam katz '使此循环变得更简单!)


为什么不剪切

剪切对于在大文件中提取列很有用,但是 forks 重复( var = $(echo ... | cut ... cut ...) )迅速过度杀伤!

这是一个正确的语法,在许多 posix shell 使用剪切,如 dougw << /a>:


比较执行时间


准备999个字段:


然后


使用 1 forks cut by field 1 forks >,对于少于1'000字段

\n'} # drop '\n' added on last field, by '<<<'

使用 mapfile ,您还可以跳过划界元素上声明数组并隐式“循环”,每个元素都在每个元素上调用一个函数:


(注意:格式字符串末端的 \ 0 ,如果您不在字符串末端关心空字段,或者它们不存在。)


但是您甚至可以使用 newline (mapfile的默认值)分隔符:


您可以使用&lt;&lt;&lt;&lt; ,并且在功能中包括一些处理,以删除newline IT添加:


基于 shell

如果您不能使用 bash 或如果您想编写可以在许多不同的外壳中使用的东西,那么您经常 use bashisms - 这包括我们在上述解决方案中使用的数组。

但是,我们不需要使用数组来循环浏览字符串的“元素”。许多壳中使用了一种语法,用于从 first 最后一个中删除字符串的子字符串。请注意,*是一个代表零或更多字符的通配符:(

,在任何解决方案中缺乏此方法是我写这个答案的主要原因;)


到目前为止 href =“ https://stackoverflow.com/posts/comments/47972612?noredirect=1”> score_under :

分别从字符串的 start end 中删除最短的匹配子字符串,和

## %% 删除最长可能的匹配子字符串。

使用上述语法,我们可以创建一种方法,通过在定界符之前或之后删除子字符串,从字符串中提取子字符串“元素”。

下面的代码块在 bash (包括mac os的 bash ), dash ksh yash> yash << /a>, zsh busybox 's ash :(

感谢 adam katz '使此循环变得更简单!)


为什么不剪切

剪切对于在大文件中提取列很有用,但是 forks 重复( var = $(echo ... | cut ... cut ...) )迅速过度杀伤!

这是一个正确的语法,在许多 posix shell 使用剪切,如 dougw << /a>:


比较执行时间


准备999个字段:


然后


使用 1 forks cut by field 1 forks >,对于少于1'000字段

\t\n'

我们可以看到,中的字符串已存储在名为 fields 的数组中,在半olons上分开:(


我们可以还使用声明-p :)


请注意,读取最快进行分割的方法,因为没有< em> forks 或调用外部资源。

定义数组后,您可以使用一个简单的循环来处理每个字段(或者,您现在定义的数组中的每个元素):


或者可以在使用移动后处理后从数组中删除每个字段方法,我喜欢的方法:


如果您只想简单地打印数组,您甚至不需要循环浏览它:


更新:最近 bash &gt; = 4.4

bash 的较新版本中,您也可以使用命令 mapfile


此语法保留特殊的chars ,新线和空字段!

如果您不想包含空字段,则可以执行以下操作:


使用 mapfile ,您还可以跳过划界元素上声明数组并隐式“循环”,每个元素都在每个元素上调用一个函数:


(注意:格式字符串末端的 \ 0 ,如果您不在字符串末端关心空字段,或者它们不存在。)


但是您甚至可以使用 newline (mapfile的默认值)分隔符:


您可以使用&lt;&lt;&lt;&lt; ,并且在功能中包括一些处理,以删除newline IT添加:


基于 shell

如果您不能使用 bash 或如果您想编写可以在许多不同的外壳中使用的东西,那么您经常 use bashisms - 这包括我们在上述解决方案中使用的数组。

但是,我们不需要使用数组来循环浏览字符串的“元素”。许多壳中使用了一种语法,用于从 first 最后一个中删除字符串的子字符串。请注意,*是一个代表零或更多字符的通配符:(

,在任何解决方案中缺乏此方法是我写这个答案的主要原因;)


到目前为止 href =“ https://stackoverflow.com/posts/comments/47972612?noredirect=1”> score_under :

分别从字符串的 start end 中删除最短的匹配子字符串,和

## %% 删除最长可能的匹配子字符串。

使用上述语法,我们可以创建一种方法,通过在定界符之前或之后删除子字符串,从字符串中提取子字符串“元素”。

下面的代码块在 bash (包括mac os的 bash ), dash ksh yash> yash << /a>, zsh busybox 's ash :(

感谢 adam katz '使此循环变得更简单!)


为什么不剪切

剪切对于在大文件中提取列很有用,但是 forks 重复( var = $(echo ... | cut ... cut ...) )迅速过度杀伤!

这是一个正确的语法,在许多 posix shell 使用剪切,如 dougw << /a>:


比较执行时间


准备999个字段:


然后


使用 1 forks cut by field 1 forks >,对于少于1'000字段

\n'}" -tc 1 -C myPubliMail # Seq: 0: Sending mail to '[email protected]', done. # Seq: 1: Sending mail to '[email protected]', done. # Seq: 2: Sending mail to 'Full Name <[email protected]>', done.

您可以使用&lt;&lt;&lt;&lt; ,并且在功能中包括一些处理,以删除newline IT添加:


基于 shell

如果您不能使用 bash 或如果您想编写可以在许多不同的外壳中使用的东西,那么您经常 use bashisms - 这包括我们在上述解决方案中使用的数组。

但是,我们不需要使用数组来循环浏览字符串的“元素”。许多壳中使用了一种语法,用于从 first 最后一个中删除字符串的子字符串。请注意,*是一个代表零或更多字符的通配符:(

,在任何解决方案中缺乏此方法是我写这个答案的主要原因;)


到目前为止 href =“ https://stackoverflow.com/posts/comments/47972612?noredirect=1”> score_under :

分别从字符串的 start end 中删除最短的匹配子字符串,和

## %% 删除最长可能的匹配子字符串。

使用上述语法,我们可以创建一种方法,通过在定界符之前或之后删除子字符串,从字符串中提取子字符串“元素”。

下面的代码块在 bash (包括mac os的 bash ), dash ksh yash> yash << /a>, zsh busybox 's ash :(

感谢 adam katz '使此循环变得更简单!)


为什么不剪切

剪切对于在大文件中提取列很有用,但是 forks 重复( var = $(echo ... | cut ... cut ...) )迅速过度杀伤!

这是一个正确的语法,在许多 posix shell 使用剪切,如 dougw << /a>:


比较执行时间


准备999个字段:


然后


使用 1 forks cut by field 1 forks >,对于少于1'000字段

\t\n'

我们可以看到,中的字符串已存储在名为 fields 的数组中,在半olons上分开:(


我们可以还使用声明-p :)


请注意,读取最快进行分割的方法,因为没有< em> forks 或调用外部资源。

定义数组后,您可以使用一个简单的循环来处理每个字段(或者,您现在定义的数组中的每个元素):


或者可以在使用移动后处理后从数组中删除每个字段方法,我喜欢的方法:


如果您只想简单地打印数组,您甚至不需要循环浏览它:


更新:最近 bash &gt; = 4.4

bash 的较新版本中,您也可以使用命令 mapfile


此语法保留特殊的chars ,新线和空字段!

如果您不想包含空字段,则可以执行以下操作:


使用 mapfile ,您还可以跳过划界元素上声明数组并隐式“循环”,每个元素都在每个元素上调用一个函数:


(注意:格式字符串末端的 \ 0 ,如果您不在字符串末端关心空字段,或者它们不存在。)


但是您甚至可以使用 newline (mapfile的默认值)分隔符:


您可以使用&lt;&lt;&lt;&lt; ,并且在功能中包括一些处理,以删除newline IT添加:


基于 shell

如果您不能使用 bash 或如果您想编写可以在许多不同的外壳中使用的东西,那么您经常 use bashisms - 这包括我们在上述解决方案中使用的数组。

但是,我们不需要使用数组来循环浏览字符串的“元素”。许多壳中使用了一种语法,用于从 first 最后一个中删除字符串的子字符串。请注意,*是一个代表零或更多字符的通配符:(

,在任何解决方案中缺乏此方法是我写这个答案的主要原因;)


到目前为止 href =“ https://stackoverflow.com/posts/comments/47972612?noredirect=1”> score_under :

分别从字符串的 start end 中删除最短的匹配子字符串,和

## %% 删除最长可能的匹配子字符串。

使用上述语法,我们可以创建一种方法,通过在定界符之前或之后删除子字符串,从字符串中提取子字符串“元素”。

下面的代码块在 bash (包括mac os的 bash ), dash ksh yash> yash << /a>, zsh busybox 's ash :(

感谢 adam katz '使此循环变得更简单!)


为什么不剪切

剪切对于在大文件中提取列很有用,但是 forks 重复( var = $(echo ... | cut ... cut ...) )迅速过度杀伤!

这是一个正确的语法,在许多 posix shell 使用剪切,如 dougw << /a>:


比较执行时间


准备999个字段:


然后


使用 1 forks cut by field 1 forks >,对于少于1'000字段

\n'} # drop '\n' added on last field, by '<<<'

使用 mapfile ,您还可以跳过划界元素上声明数组并隐式“循环”,每个元素都在每个元素上调用一个函数:


(注意:格式字符串末端的 \ 0 ,如果您不在字符串末端关心空字段,或者它们不存在。)


但是您甚至可以使用 newline (mapfile的默认值)分隔符:


您可以使用&lt;&lt;&lt;&lt; ,并且在功能中包括一些处理,以删除newline IT添加:


基于 shell

如果您不能使用 bash 或如果您想编写可以在许多不同的外壳中使用的东西,那么您经常 use bashisms - 这包括我们在上述解决方案中使用的数组。

但是,我们不需要使用数组来循环浏览字符串的“元素”。许多壳中使用了一种语法,用于从 first 最后一个中删除字符串的子字符串。请注意,*是一个代表零或更多字符的通配符:(

,在任何解决方案中缺乏此方法是我写这个答案的主要原因;)


到目前为止 href =“ https://stackoverflow.com/posts/comments/47972612?noredirect=1”> score_under :

分别从字符串的 start end 中删除最短的匹配子字符串,和

## %% 删除最长可能的匹配子字符串。

使用上述语法,我们可以创建一种方法,通过在定界符之前或之后删除子字符串,从字符串中提取子字符串“元素”。

下面的代码块在 bash (包括mac os的 bash ), dash ksh yash> yash << /a>, zsh busybox 's ash :(

感谢 adam katz '使此循环变得更简单!)


为什么不剪切

剪切对于在大文件中提取列很有用,但是 forks 重复( var = $(echo ... | cut ... cut ...) )迅速过度杀伤!

这是一个正确的语法,在许多 posix shell 使用剪切,如 dougw << /a>:


比较执行时间


准备999个字段:


然后


使用 1 forks cut by field 1 forks >,对于少于1'000字段

\t\n'

我们可以看到,中的字符串已存储在名为 fields 的数组中,在半olons上分开:(


我们可以还使用声明-p :)


请注意,读取最快进行分割的方法,因为没有< em> forks 或调用外部资源。

定义数组后,您可以使用一个简单的循环来处理每个字段(或者,您现在定义的数组中的每个元素):


或者可以在使用移动后处理后从数组中删除每个字段方法,我喜欢的方法:


如果您只想简单地打印数组,您甚至不需要循环浏览它:


更新:最近 bash &gt; = 4.4

bash 的较新版本中,您也可以使用命令 mapfile


此语法保留特殊的chars ,新线和空字段!

如果您不想包含空字段,则可以执行以下操作:


使用 mapfile ,您还可以跳过划界元素上声明数组并隐式“循环”,每个元素都在每个元素上调用一个函数:


(注意:格式字符串末端的 \ 0 ,如果您不在字符串末端关心空字段,或者它们不存在。)


但是您甚至可以使用 newline (mapfile的默认值)分隔符:


您可以使用&lt;&lt;&lt;&lt; ,并且在功能中包括一些处理,以删除newline IT添加:


基于 shell

如果您不能使用 bash 或如果您想编写可以在许多不同的外壳中使用的东西,那么您经常 use bashisms - 这包括我们在上述解决方案中使用的数组。

但是,我们不需要使用数组来循环浏览字符串的“元素”。许多壳中使用了一种语法,用于从 first 最后一个中删除字符串的子字符串。请注意,*是一个代表零或更多字符的通配符:(

,在任何解决方案中缺乏此方法是我写这个答案的主要原因;)


到目前为止 href =“ https://stackoverflow.com/posts/comments/47972612?noredirect=1”> score_under :

分别从字符串的 start end 中删除最短的匹配子字符串,和

## %% 删除最长可能的匹配子字符串。

使用上述语法,我们可以创建一种方法,通过在定界符之前或之后删除子字符串,从字符串中提取子字符串“元素”。

下面的代码块在 bash (包括mac os的 bash ), dash ksh yash> yash << /a>, zsh busybox 's ash :(

感谢 adam katz '使此循环变得更简单!)


为什么不剪切

剪切对于在大文件中提取列很有用,但是 forks 重复( var = $(echo ... | cut ... cut ...) )迅速过度杀伤!

这是一个正确的语法,在许多 posix shell 使用剪切,如 dougw << /a>:


比较执行时间


准备999个字段:


然后


使用 1 forks cut by field 1 forks >,对于少于1'000字段

\n'}" printf "Seq: %6d: Sending mail to '%s'..." $seq "$dest" # mail -s "This is not a spam..." "$dest" </path/to/body printf "\e[3D, done.\n" } mapfile <<<"$IN" -td \; -c 1 -C myPubliMail # Renders the same output: # Seq: 0: Sending mail to '[email protected]', done. # Seq: 1: Sending mail to '[email protected]', done. # Seq: 2: Sending mail to 'Full Name <[email protected]>', done.

基于 shell

如果您不能使用 bash 或如果您想编写可以在许多不同的外壳中使用的东西,那么您经常 use bashisms - 这包括我们在上述解决方案中使用的数组。

但是,我们不需要使用数组来循环浏览字符串的“元素”。许多壳中使用了一种语法,用于从 first 最后一个中删除字符串的子字符串。请注意,*是一个代表零或更多字符的通配符:(

,在任何解决方案中缺乏此方法是我写这个答案的主要原因;)


到目前为止 href =“ https://stackoverflow.com/posts/comments/47972612?noredirect=1”> score_under :

分别从字符串的 start end 中删除最短的匹配子字符串,和

## %% 删除最长可能的匹配子字符串。

使用上述语法,我们可以创建一种方法,通过在定界符之前或之后删除子字符串,从字符串中提取子字符串“元素”。

下面的代码块在 bash (包括mac os的 bash ), dash ksh yash> yash << /a>, zsh busybox 's ash :(

感谢 adam katz '使此循环变得更简单!)


为什么不剪切

剪切对于在大文件中提取列很有用,但是 forks 重复( var = $(echo ... | cut ... cut ...) )迅速过度杀伤!

这是一个正确的语法,在许多 posix shell 使用剪切,如 dougw << /a>:


比较执行时间


准备999个字段:


然后


使用 1 forks cut by field 1 forks >,对于少于1'000字段

\t\n'

我们可以看到,中的字符串已存储在名为 fields 的数组中,在半olons上分开:(


我们可以还使用声明-p :)


请注意,读取最快进行分割的方法,因为没有< em> forks 或调用外部资源。

定义数组后,您可以使用一个简单的循环来处理每个字段(或者,您现在定义的数组中的每个元素):


或者可以在使用移动后处理后从数组中删除每个字段方法,我喜欢的方法:


如果您只想简单地打印数组,您甚至不需要循环浏览它:


更新:最近 bash &gt; = 4.4

bash 的较新版本中,您也可以使用命令 mapfile


此语法保留特殊的chars ,新线和空字段!

如果您不想包含空字段,则可以执行以下操作:


使用 mapfile ,您还可以跳过划界元素上声明数组并隐式“循环”,每个元素都在每个元素上调用一个函数:


(注意:格式字符串末端的 \ 0 ,如果您不在字符串末端关心空字段,或者它们不存在。)


但是您甚至可以使用 newline (mapfile的默认值)分隔符:


您可以使用&lt;&lt;&lt;&lt; ,并且在功能中包括一些处理,以删除newline IT添加:


基于 shell

如果您不能使用 bash 或如果您想编写可以在许多不同的外壳中使用的东西,那么您经常 use bashisms - 这包括我们在上述解决方案中使用的数组。

但是,我们不需要使用数组来循环浏览字符串的“元素”。许多壳中使用了一种语法,用于从 first 最后一个中删除字符串的子字符串。请注意,*是一个代表零或更多字符的通配符:(

,在任何解决方案中缺乏此方法是我写这个答案的主要原因;)


到目前为止 href =“ https://stackoverflow.com/posts/comments/47972612?noredirect=1”> score_under :

分别从字符串的 start end 中删除最短的匹配子字符串,和

## %% 删除最长可能的匹配子字符串。

使用上述语法,我们可以创建一种方法,通过在定界符之前或之后删除子字符串,从字符串中提取子字符串“元素”。

下面的代码块在 bash (包括mac os的 bash ), dash ksh yash> yash << /a>, zsh busybox 's ash :(

感谢 adam katz '使此循环变得更简单!)


为什么不剪切

剪切对于在大文件中提取列很有用,但是 forks 重复( var = $(echo ... | cut ... cut ...) )迅速过度杀伤!

这是一个正确的语法,在许多 posix shell 使用剪切,如 dougw << /a>:


比较执行时间


准备999个字段:


然后


使用 1 forks cut by field 1 forks >,对于少于1'000字段

\n'} # drop '\n' added on last field, by '<<<'

使用 mapfile ,您还可以跳过划界元素上声明数组并隐式“循环”,每个元素都在每个元素上调用一个函数:


(注意:格式字符串末端的 \ 0 ,如果您不在字符串末端关心空字段,或者它们不存在。)


但是您甚至可以使用 newline (mapfile的默认值)分隔符:


您可以使用&lt;&lt;&lt;&lt; ,并且在功能中包括一些处理,以删除newline IT添加:


基于 shell

如果您不能使用 bash 或如果您想编写可以在许多不同的外壳中使用的东西,那么您经常 use bashisms - 这包括我们在上述解决方案中使用的数组。

但是,我们不需要使用数组来循环浏览字符串的“元素”。许多壳中使用了一种语法,用于从 first 最后一个中删除字符串的子字符串。请注意,*是一个代表零或更多字符的通配符:(

,在任何解决方案中缺乏此方法是我写这个答案的主要原因;)


到目前为止 href =“ https://stackoverflow.com/posts/comments/47972612?noredirect=1”> score_under :

分别从字符串的 start end 中删除最短的匹配子字符串,和

## %% 删除最长可能的匹配子字符串。

使用上述语法,我们可以创建一种方法,通过在定界符之前或之后删除子字符串,从字符串中提取子字符串“元素”。

下面的代码块在 bash (包括mac os的 bash ), dash ksh yash> yash << /a>, zsh busybox 's ash :(

感谢 adam katz '使此循环变得更简单!)


为什么不剪切

剪切对于在大文件中提取列很有用,但是 forks 重复( var = $(echo ... | cut ... cut ...) )迅速过度杀伤!

这是一个正确的语法,在许多 posix shell 使用剪切,如 dougw << /a>:


比较执行时间


准备999个字段:


然后


使用 1 forks cut by field 1 forks >,对于少于1'000字段

\t\n'

我们可以看到,中的字符串已存储在名为 fields 的数组中,在半olons上分开:(


我们可以还使用声明-p :)


请注意,读取最快进行分割的方法,因为没有< em> forks 或调用外部资源。

定义数组后,您可以使用一个简单的循环来处理每个字段(或者,您现在定义的数组中的每个元素):


或者可以在使用移动后处理后从数组中删除每个字段方法,我喜欢的方法:


如果您只想简单地打印数组,您甚至不需要循环浏览它:


更新:最近 bash &gt; = 4.4

bash 的较新版本中,您也可以使用命令 mapfile


此语法保留特殊的chars ,新线和空字段!

如果您不想包含空字段,则可以执行以下操作:


使用 mapfile ,您还可以跳过划界元素上声明数组并隐式“循环”,每个元素都在每个元素上调用一个函数:


(注意:格式字符串末端的 \ 0 ,如果您不在字符串末端关心空字段,或者它们不存在。)


但是您甚至可以使用 newline (mapfile的默认值)分隔符:


您可以使用&lt;&lt;&lt;&lt; ,并且在功能中包括一些处理,以删除newline IT添加:


基于 shell

如果您不能使用 bash 或如果您想编写可以在许多不同的外壳中使用的东西,那么您经常 use bashisms - 这包括我们在上述解决方案中使用的数组。

但是,我们不需要使用数组来循环浏览字符串的“元素”。许多壳中使用了一种语法,用于从 first 最后一个中删除字符串的子字符串。请注意,*是一个代表零或更多字符的通配符:(

,在任何解决方案中缺乏此方法是我写这个答案的主要原因;)


到目前为止 href =“ https://stackoverflow.com/posts/comments/47972612?noredirect=1”> score_under :

分别从字符串的 start end 中删除最短的匹配子字符串,和

## %% 删除最长可能的匹配子字符串。

使用上述语法,我们可以创建一种方法,通过在定界符之前或之后删除子字符串,从字符串中提取子字符串“元素”。

下面的代码块在 bash (包括mac os的 bash ), dash ksh yash> yash << /a>, zsh busybox 's ash :(

感谢 adam katz '使此循环变得更简单!)


为什么不剪切

剪切对于在大文件中提取列很有用,但是 forks 重复( var = $(echo ... | cut ... cut ...) )迅速过度杀伤!

这是一个正确的语法,在许多 posix shell 使用剪切,如 dougw << /a>:


比较执行时间


准备999个字段:


然后


使用 1 forks cut by field 1 forks >,对于少于1'000字段

\n'}" -tc 1 -C myPubliMail # Seq: 0: Sending mail to '[email protected]', done. # Seq: 1: Sending mail to '[email protected]', done. # Seq: 2: Sending mail to 'Full Name <[email protected]>', done.

您可以使用&lt;&lt;&lt;&lt; ,并且在功能中包括一些处理,以删除newline IT添加:


基于 shell

如果您不能使用 bash 或如果您想编写可以在许多不同的外壳中使用的东西,那么您经常 use bashisms - 这包括我们在上述解决方案中使用的数组。

但是,我们不需要使用数组来循环浏览字符串的“元素”。许多壳中使用了一种语法,用于从 first 最后一个中删除字符串的子字符串。请注意,*是一个代表零或更多字符的通配符:(

,在任何解决方案中缺乏此方法是我写这个答案的主要原因;)


到目前为止 href =“ https://stackoverflow.com/posts/comments/47972612?noredirect=1”> score_under :

分别从字符串的 start end 中删除最短的匹配子字符串,和

## %% 删除最长可能的匹配子字符串。

使用上述语法,我们可以创建一种方法,通过在定界符之前或之后删除子字符串,从字符串中提取子字符串“元素”。

下面的代码块在 bash (包括mac os的 bash ), dash ksh yash> yash << /a>, zsh busybox 's ash :(

感谢 adam katz '使此循环变得更简单!)


为什么不剪切

剪切对于在大文件中提取列很有用,但是 forks 重复( var = $(echo ... | cut ... cut ...) )迅速过度杀伤!

这是一个正确的语法,在许多 posix shell 使用剪切,如 dougw << /a>:


比较执行时间


准备999个字段:


然后


使用 1 forks cut by field 1 forks >,对于少于1'000字段

\t\n'

我们可以看到,中的字符串已存储在名为 fields 的数组中,在半olons上分开:(


我们可以还使用声明-p :)


请注意,读取最快进行分割的方法,因为没有< em> forks 或调用外部资源。

定义数组后,您可以使用一个简单的循环来处理每个字段(或者,您现在定义的数组中的每个元素):


或者可以在使用移动后处理后从数组中删除每个字段方法,我喜欢的方法:


如果您只想简单地打印数组,您甚至不需要循环浏览它:


更新:最近 bash &gt; = 4.4

bash 的较新版本中,您也可以使用命令 mapfile


此语法保留特殊的chars ,新线和空字段!

如果您不想包含空字段,则可以执行以下操作:


使用 mapfile ,您还可以跳过划界元素上声明数组并隐式“循环”,每个元素都在每个元素上调用一个函数:


(注意:格式字符串末端的 \ 0 ,如果您不在字符串末端关心空字段,或者它们不存在。)


但是您甚至可以使用 newline (mapfile的默认值)分隔符:


您可以使用&lt;&lt;&lt;&lt; ,并且在功能中包括一些处理,以删除newline IT添加:


基于 shell

如果您不能使用 bash 或如果您想编写可以在许多不同的外壳中使用的东西,那么您经常 use bashisms - 这包括我们在上述解决方案中使用的数组。

但是,我们不需要使用数组来循环浏览字符串的“元素”。许多壳中使用了一种语法,用于从 first 最后一个中删除字符串的子字符串。请注意,*是一个代表零或更多字符的通配符:(

,在任何解决方案中缺乏此方法是我写这个答案的主要原因;)


到目前为止 href =“ https://stackoverflow.com/posts/comments/47972612?noredirect=1”> score_under :

分别从字符串的 start end 中删除最短的匹配子字符串,和

## %% 删除最长可能的匹配子字符串。

使用上述语法,我们可以创建一种方法,通过在定界符之前或之后删除子字符串,从字符串中提取子字符串“元素”。

下面的代码块在 bash (包括mac os的 bash ), dash ksh yash> yash << /a>, zsh busybox 's ash :(

感谢 adam katz '使此循环变得更简单!)


为什么不剪切

剪切对于在大文件中提取列很有用,但是 forks 重复( var = $(echo ... | cut ... cut ...) )迅速过度杀伤!

这是一个正确的语法,在许多 posix shell 使用剪切,如 dougw << /a>:


比较执行时间


准备999个字段:


然后


使用 1 forks cut by field 1 forks >,对于少于1'000字段

\n'} # drop '\n' added on last field, by '<<<'

使用 mapfile ,您还可以跳过划界元素上声明数组并隐式“循环”,每个元素都在每个元素上调用一个函数:


(注意:格式字符串末端的 \ 0 ,如果您不在字符串末端关心空字段,或者它们不存在。)


但是您甚至可以使用 newline (mapfile的默认值)分隔符:


您可以使用&lt;&lt;&lt;&lt; ,并且在功能中包括一些处理,以删除newline IT添加:


基于 shell

如果您不能使用 bash 或如果您想编写可以在许多不同的外壳中使用的东西,那么您经常 use bashisms - 这包括我们在上述解决方案中使用的数组。

但是,我们不需要使用数组来循环浏览字符串的“元素”。许多壳中使用了一种语法,用于从 first 最后一个中删除字符串的子字符串。请注意,*是一个代表零或更多字符的通配符:(

,在任何解决方案中缺乏此方法是我写这个答案的主要原因;)


到目前为止 href =“ https://stackoverflow.com/posts/comments/47972612?noredirect=1”> score_under :

分别从字符串的 start end 中删除最短的匹配子字符串,和

## %% 删除最长可能的匹配子字符串。

使用上述语法,我们可以创建一种方法,通过在定界符之前或之后删除子字符串,从字符串中提取子字符串“元素”。

下面的代码块在 bash (包括mac os的 bash ), dash ksh yash> yash << /a>, zsh busybox 's ash :(

感谢 adam katz '使此循环变得更简单!)


为什么不剪切

剪切对于在大文件中提取列很有用,但是 forks 重复( var = $(echo ... | cut ... cut ...) )迅速过度杀伤!

这是一个正确的语法,在许多 posix shell 使用剪切,如 dougw << /a>:


比较执行时间


准备999个字段:


然后


使用 1 forks cut by field 1 forks >,对于少于1'000字段

\t\n'

我们可以看到,中的字符串已存储在名为 fields 的数组中,在半olons上分开:(


我们可以还使用声明-p :)


请注意,读取最快进行分割的方法,因为没有< em> forks 或调用外部资源。

定义数组后,您可以使用一个简单的循环来处理每个字段(或者,您现在定义的数组中的每个元素):


或者可以在使用移动后处理后从数组中删除每个字段方法,我喜欢的方法:


如果您只想简单地打印数组,您甚至不需要循环浏览它:


更新:最近 bash &gt; = 4.4

bash 的较新版本中,您也可以使用命令 mapfile


此语法保留特殊的chars ,新线和空字段!

如果您不想包含空字段,则可以执行以下操作:


使用 mapfile ,您还可以跳过划界元素上声明数组并隐式“循环”,每个元素都在每个元素上调用一个函数:


(注意:格式字符串末端的 \ 0 ,如果您不在字符串末端关心空字段,或者它们不存在。)


但是您甚至可以使用 newline (mapfile的默认值)分隔符:


您可以使用&lt;&lt;&lt;&lt; ,并且在功能中包括一些处理,以删除newline IT添加:


基于 shell

如果您不能使用 bash 或如果您想编写可以在许多不同的外壳中使用的东西,那么您经常 use bashisms - 这包括我们在上述解决方案中使用的数组。

但是,我们不需要使用数组来循环浏览字符串的“元素”。许多壳中使用了一种语法,用于从 first 最后一个中删除字符串的子字符串。请注意,*是一个代表零或更多字符的通配符:(

,在任何解决方案中缺乏此方法是我写这个答案的主要原因;)


到目前为止 href =“ https://stackoverflow.com/posts/comments/47972612?noredirect=1”> score_under :

分别从字符串的 start end 中删除最短的匹配子字符串,和

## %% 删除最长可能的匹配子字符串。

使用上述语法,我们可以创建一种方法,通过在定界符之前或之后删除子字符串,从字符串中提取子字符串“元素”。

下面的代码块在 bash (包括mac os的 bash ), dash ksh yash> yash << /a>, zsh busybox 's ash :(

感谢 adam katz '使此循环变得更简单!)


为什么不剪切

剪切对于在大文件中提取列很有用,但是 forks 重复( var = $(echo ... | cut ... cut ...) )迅速过度杀伤!

这是一个正确的语法,在许多 posix shell 使用剪切,如 dougw << /a>:


比较执行时间


准备999个字段:


然后


使用 1 forks cut by field 1 forks >,对于少于1'000字段

\n'}" [[ $2 ]] && printf "> [%s]\n" "$dest" } mapfile <<<"${1//;/

准备999个字段:


然后


使用 1 forks cut by field 1 forks >,对于少于1'000字段

\t\n'

我们可以看到,中的字符串已存储在名为 fields 的数组中,在半olons上分开:(


我们可以还使用声明-p :)


请注意,读取最快进行分割的方法,因为没有< em> forks 或调用外部资源。

定义数组后,您可以使用一个简单的循环来处理每个字段(或者,您现在定义的数组中的每个元素):


或者可以在使用移动后处理后从数组中删除每个字段方法,我喜欢的方法:


如果您只想简单地打印数组,您甚至不需要循环浏览它:


更新:最近 bash &gt; = 4.4

bash 的较新版本中,您也可以使用命令 mapfile


此语法保留特殊的chars ,新线和空字段!

如果您不想包含空字段,则可以执行以下操作:


使用 mapfile ,您还可以跳过划界元素上声明数组并隐式“循环”,每个元素都在每个元素上调用一个函数:


(注意:格式字符串末端的 \ 0 ,如果您不在字符串末端关心空字段,或者它们不存在。)


但是您甚至可以使用 newline (mapfile的默认值)分隔符:


您可以使用&lt;&lt;&lt;&lt; ,并且在功能中包括一些处理,以删除newline IT添加:


基于 shell

如果您不能使用 bash 或如果您想编写可以在许多不同的外壳中使用的东西,那么您经常 use bashisms - 这包括我们在上述解决方案中使用的数组。

但是,我们不需要使用数组来循环浏览字符串的“元素”。许多壳中使用了一种语法,用于从 first 最后一个中删除字符串的子字符串。请注意,*是一个代表零或更多字符的通配符:(

,在任何解决方案中缺乏此方法是我写这个答案的主要原因;)


到目前为止 href =“ https://stackoverflow.com/posts/comments/47972612?noredirect=1”> score_under :

分别从字符串的 start end 中删除最短的匹配子字符串,和

## %% 删除最长可能的匹配子字符串。

使用上述语法,我们可以创建一种方法,通过在定界符之前或之后删除子字符串,从字符串中提取子字符串“元素”。

下面的代码块在 bash (包括mac os的 bash ), dash ksh yash> yash << /a>, zsh busybox 's ash :(

感谢 adam katz '使此循环变得更简单!)


为什么不剪切

剪切对于在大文件中提取列很有用,但是 forks 重复( var = $(echo ... | cut ... cut ...) )迅速过度杀伤!

这是一个正确的语法,在许多 posix shell 使用剪切,如 dougw << /a>:


比较执行时间


准备999个字段:


然后


使用 1 forks cut by field 1 forks >,对于少于1'000字段

\n'} # drop '\n' added on last field, by '<<<'

使用 mapfile ,您还可以跳过划界元素上声明数组并隐式“循环”,每个元素都在每个元素上调用一个函数:


(注意:格式字符串末端的 \ 0 ,如果您不在字符串末端关心空字段,或者它们不存在。)


但是您甚至可以使用 newline (mapfile的默认值)分隔符:


您可以使用&lt;&lt;&lt;&lt; ,并且在功能中包括一些处理,以删除newline IT添加:


基于 shell

如果您不能使用 bash 或如果您想编写可以在许多不同的外壳中使用的东西,那么您经常 use bashisms - 这包括我们在上述解决方案中使用的数组。

但是,我们不需要使用数组来循环浏览字符串的“元素”。许多壳中使用了一种语法,用于从 first 最后一个中删除字符串的子字符串。请注意,*是一个代表零或更多字符的通配符:(

,在任何解决方案中缺乏此方法是我写这个答案的主要原因;)


到目前为止 href =“ https://stackoverflow.com/posts/comments/47972612?noredirect=1”> score_under :

分别从字符串的 start end 中删除最短的匹配子字符串,和

## %% 删除最长可能的匹配子字符串。

使用上述语法,我们可以创建一种方法,通过在定界符之前或之后删除子字符串,从字符串中提取子字符串“元素”。

下面的代码块在 bash (包括mac os的 bash ), dash ksh yash> yash << /a>, zsh busybox 's ash :(

感谢 adam katz '使此循环变得更简单!)


为什么不剪切

剪切对于在大文件中提取列很有用,但是 forks 重复( var = $(echo ... | cut ... cut ...) )迅速过度杀伤!

这是一个正确的语法,在许多 posix shell 使用剪切,如 dougw << /a>:


比较执行时间


准备999个字段:


然后


使用 1 forks cut by field 1 forks >,对于少于1'000字段

\t\n'

我们可以看到,中的字符串已存储在名为 fields 的数组中,在半olons上分开:(


我们可以还使用声明-p :)


请注意,读取最快进行分割的方法,因为没有< em> forks 或调用外部资源。

定义数组后,您可以使用一个简单的循环来处理每个字段(或者,您现在定义的数组中的每个元素):


或者可以在使用移动后处理后从数组中删除每个字段方法,我喜欢的方法:


如果您只想简单地打印数组,您甚至不需要循环浏览它:


更新:最近 bash &gt; = 4.4

bash 的较新版本中,您也可以使用命令 mapfile


此语法保留特殊的chars ,新线和空字段!

如果您不想包含空字段,则可以执行以下操作:


使用 mapfile ,您还可以跳过划界元素上声明数组并隐式“循环”,每个元素都在每个元素上调用一个函数:


(注意:格式字符串末端的 \ 0 ,如果您不在字符串末端关心空字段,或者它们不存在。)


但是您甚至可以使用 newline (mapfile的默认值)分隔符:


您可以使用&lt;&lt;&lt;&lt; ,并且在功能中包括一些处理,以删除newline IT添加:


基于 shell

如果您不能使用 bash 或如果您想编写可以在许多不同的外壳中使用的东西,那么您经常 use bashisms - 这包括我们在上述解决方案中使用的数组。

但是,我们不需要使用数组来循环浏览字符串的“元素”。许多壳中使用了一种语法,用于从 first 最后一个中删除字符串的子字符串。请注意,*是一个代表零或更多字符的通配符:(

,在任何解决方案中缺乏此方法是我写这个答案的主要原因;)


到目前为止 href =“ https://stackoverflow.com/posts/comments/47972612?noredirect=1”> score_under :

分别从字符串的 start end 中删除最短的匹配子字符串,和

## %% 删除最长可能的匹配子字符串。

使用上述语法,我们可以创建一种方法,通过在定界符之前或之后删除子字符串,从字符串中提取子字符串“元素”。

下面的代码块在 bash (包括mac os的 bash ), dash ksh yash> yash << /a>, zsh busybox 's ash :(

感谢 adam katz '使此循环变得更简单!)


为什么不剪切

剪切对于在大文件中提取列很有用,但是 forks 重复( var = $(echo ... | cut ... cut ...) )迅速过度杀伤!

这是一个正确的语法,在许多 posix shell 使用剪切,如 dougw << /a>:


比较执行时间


准备999个字段:


然后


使用 1 forks cut by field 1 forks >,对于少于1'000字段

\n'}" -tc 1 -C myPubliMail # Seq: 0: Sending mail to '[email protected]', done. # Seq: 1: Sending mail to '[email protected]', done. # Seq: 2: Sending mail to 'Full Name <[email protected]>', done.

您可以使用&lt;&lt;&lt;&lt; ,并且在功能中包括一些处理,以删除newline IT添加:


基于 shell

如果您不能使用 bash 或如果您想编写可以在许多不同的外壳中使用的东西,那么您经常 use bashisms - 这包括我们在上述解决方案中使用的数组。

但是,我们不需要使用数组来循环浏览字符串的“元素”。许多壳中使用了一种语法,用于从 first 最后一个中删除字符串的子字符串。请注意,*是一个代表零或更多字符的通配符:(

,在任何解决方案中缺乏此方法是我写这个答案的主要原因;)


到目前为止 href =“ https://stackoverflow.com/posts/comments/47972612?noredirect=1”> score_under :

分别从字符串的 start end 中删除最短的匹配子字符串,和

## %% 删除最长可能的匹配子字符串。

使用上述语法,我们可以创建一种方法,通过在定界符之前或之后删除子字符串,从字符串中提取子字符串“元素”。

下面的代码块在 bash (包括mac os的 bash ), dash ksh yash> yash << /a>, zsh busybox 's ash :(

感谢 adam katz '使此循环变得更简单!)


为什么不剪切

剪切对于在大文件中提取列很有用,但是 forks 重复( var = $(echo ... | cut ... cut ...) )迅速过度杀伤!

这是一个正确的语法,在许多 posix shell 使用剪切,如 dougw << /a>:


比较执行时间


准备999个字段:


然后


使用 1 forks cut by field 1 forks >,对于少于1'000字段

\t\n'

我们可以看到,中的字符串已存储在名为 fields 的数组中,在半olons上分开:(


我们可以还使用声明-p :)


请注意,读取最快进行分割的方法,因为没有< em> forks 或调用外部资源。

定义数组后,您可以使用一个简单的循环来处理每个字段(或者,您现在定义的数组中的每个元素):


或者可以在使用移动后处理后从数组中删除每个字段方法,我喜欢的方法:


如果您只想简单地打印数组,您甚至不需要循环浏览它:


更新:最近 bash &gt; = 4.4

bash 的较新版本中,您也可以使用命令 mapfile


此语法保留特殊的chars ,新线和空字段!

如果您不想包含空字段,则可以执行以下操作:


使用 mapfile ,您还可以跳过划界元素上声明数组并隐式“循环”,每个元素都在每个元素上调用一个函数:


(注意:格式字符串末端的 \ 0 ,如果您不在字符串末端关心空字段,或者它们不存在。)


但是您甚至可以使用 newline (mapfile的默认值)分隔符:


您可以使用&lt;&lt;&lt;&lt; ,并且在功能中包括一些处理,以删除newline IT添加:


基于 shell

如果您不能使用 bash 或如果您想编写可以在许多不同的外壳中使用的东西,那么您经常 use bashisms - 这包括我们在上述解决方案中使用的数组。

但是,我们不需要使用数组来循环浏览字符串的“元素”。许多壳中使用了一种语法,用于从 first 最后一个中删除字符串的子字符串。请注意,*是一个代表零或更多字符的通配符:(

,在任何解决方案中缺乏此方法是我写这个答案的主要原因;)


到目前为止 href =“ https://stackoverflow.com/posts/comments/47972612?noredirect=1”> score_under :

分别从字符串的 start end 中删除最短的匹配子字符串,和

## %% 删除最长可能的匹配子字符串。

使用上述语法,我们可以创建一种方法,通过在定界符之前或之后删除子字符串,从字符串中提取子字符串“元素”。

下面的代码块在 bash (包括mac os的 bash ), dash ksh yash> yash << /a>, zsh busybox 's ash :(

感谢 adam katz '使此循环变得更简单!)


为什么不剪切

剪切对于在大文件中提取列很有用,但是 forks 重复( var = $(echo ... | cut ... cut ...) )迅速过度杀伤!

这是一个正确的语法,在许多 posix shell 使用剪切,如 dougw << /a>:


比较执行时间


准备999个字段:


然后


使用 1 forks cut by field 1 forks >,对于少于1'000字段

\n'} # drop '\n' added on last field, by '<<<'

使用 mapfile ,您还可以跳过划界元素上声明数组并隐式“循环”,每个元素都在每个元素上调用一个函数:


(注意:格式字符串末端的 \ 0 ,如果您不在字符串末端关心空字段,或者它们不存在。)


但是您甚至可以使用 newline (mapfile的默认值)分隔符:


您可以使用&lt;&lt;&lt;&lt; ,并且在功能中包括一些处理,以删除newline IT添加:


基于 shell

如果您不能使用 bash 或如果您想编写可以在许多不同的外壳中使用的东西,那么您经常 use bashisms - 这包括我们在上述解决方案中使用的数组。

但是,我们不需要使用数组来循环浏览字符串的“元素”。许多壳中使用了一种语法,用于从 first 最后一个中删除字符串的子字符串。请注意,*是一个代表零或更多字符的通配符:(

,在任何解决方案中缺乏此方法是我写这个答案的主要原因;)


到目前为止 href =“ https://stackoverflow.com/posts/comments/47972612?noredirect=1”> score_under :

分别从字符串的 start end 中删除最短的匹配子字符串,和

## %% 删除最长可能的匹配子字符串。

使用上述语法,我们可以创建一种方法,通过在定界符之前或之后删除子字符串,从字符串中提取子字符串“元素”。

下面的代码块在 bash (包括mac os的 bash ), dash ksh yash> yash << /a>, zsh busybox 's ash :(

感谢 adam katz '使此循环变得更简单!)


为什么不剪切

剪切对于在大文件中提取列很有用,但是 forks 重复( var = $(echo ... | cut ... cut ...) )迅速过度杀伤!

这是一个正确的语法,在许多 posix shell 使用剪切,如 dougw << /a>:


比较执行时间


准备999个字段:


然后


使用 1 forks cut by field 1 forks >,对于少于1'000字段

\t\n'

我们可以看到,中的字符串已存储在名为 fields 的数组中,在半olons上分开:(


我们可以还使用声明-p :)


请注意,读取最快进行分割的方法,因为没有< em> forks 或调用外部资源。

定义数组后,您可以使用一个简单的循环来处理每个字段(或者,您现在定义的数组中的每个元素):


或者可以在使用移动后处理后从数组中删除每个字段方法,我喜欢的方法:


如果您只想简单地打印数组,您甚至不需要循环浏览它:


更新:最近 bash &gt; = 4.4

bash 的较新版本中,您也可以使用命令 mapfile


此语法保留特殊的chars ,新线和空字段!

如果您不想包含空字段,则可以执行以下操作:


使用 mapfile ,您还可以跳过划界元素上声明数组并隐式“循环”,每个元素都在每个元素上调用一个函数:


(注意:格式字符串末端的 \ 0 ,如果您不在字符串末端关心空字段,或者它们不存在。)


但是您甚至可以使用 newline (mapfile的默认值)分隔符:


您可以使用&lt;&lt;&lt;&lt; ,并且在功能中包括一些处理,以删除newline IT添加:


基于 shell

如果您不能使用 bash 或如果您想编写可以在许多不同的外壳中使用的东西,那么您经常 use bashisms - 这包括我们在上述解决方案中使用的数组。

但是,我们不需要使用数组来循环浏览字符串的“元素”。许多壳中使用了一种语法,用于从 first 最后一个中删除字符串的子字符串。请注意,*是一个代表零或更多字符的通配符:(

,在任何解决方案中缺乏此方法是我写这个答案的主要原因;)


到目前为止 href =“ https://stackoverflow.com/posts/comments/47972612?noredirect=1”> score_under :

分别从字符串的 start end 中删除最短的匹配子字符串,和

## %% 删除最长可能的匹配子字符串。

使用上述语法,我们可以创建一种方法,通过在定界符之前或之后删除子字符串,从字符串中提取子字符串“元素”。

下面的代码块在 bash (包括mac os的 bash ), dash ksh yash> yash << /a>, zsh busybox 's ash :(

感谢 adam katz '使此循环变得更简单!)


为什么不剪切

剪切对于在大文件中提取列很有用,但是 forks 重复( var = $(echo ... | cut ... cut ...) )迅速过度杀伤!

这是一个正确的语法,在许多 posix shell 使用剪切,如 dougw << /a>:


比较执行时间


准备999个字段:


然后


使用 1 forks cut by field 1 forks >,对于少于1'000字段

\n'}" printf "Seq: %6d: Sending mail to '%s'..." $seq "$dest" # mail -s "This is not a spam..." "$dest" </path/to/body printf "\e[3D, done.\n" } mapfile <<<"$IN" -td \; -c 1 -C myPubliMail # Renders the same output: # Seq: 0: Sending mail to '[email protected]', done. # Seq: 1: Sending mail to '[email protected]', done. # Seq: 2: Sending mail to 'Full Name <[email protected]>', done.

基于 shell

如果您不能使用 bash 或如果您想编写可以在许多不同的外壳中使用的东西,那么您经常 use bashisms - 这包括我们在上述解决方案中使用的数组。

但是,我们不需要使用数组来循环浏览字符串的“元素”。许多壳中使用了一种语法,用于从 first 最后一个中删除字符串的子字符串。请注意,*是一个代表零或更多字符的通配符:(

,在任何解决方案中缺乏此方法是我写这个答案的主要原因;)


到目前为止 href =“ https://stackoverflow.com/posts/comments/47972612?noredirect=1”> score_under :

分别从字符串的 start end 中删除最短的匹配子字符串,和

## %% 删除最长可能的匹配子字符串。

使用上述语法,我们可以创建一种方法,通过在定界符之前或之后删除子字符串,从字符串中提取子字符串“元素”。

下面的代码块在 bash (包括mac os的 bash ), dash ksh yash> yash << /a>, zsh busybox 's ash :(

感谢 adam katz '使此循环变得更简单!)


为什么不剪切

剪切对于在大文件中提取列很有用,但是 forks 重复( var = $(echo ... | cut ... cut ...) )迅速过度杀伤!

这是一个正确的语法,在许多 posix shell 使用剪切,如 dougw << /a>:


比较执行时间


准备999个字段:


然后


使用 1 forks cut by field 1 forks >,对于少于1'000字段

\t\n'

我们可以看到,中的字符串已存储在名为 fields 的数组中,在半olons上分开:(


我们可以还使用声明-p :)


请注意,读取最快进行分割的方法,因为没有< em> forks 或调用外部资源。

定义数组后,您可以使用一个简单的循环来处理每个字段(或者,您现在定义的数组中的每个元素):


或者可以在使用移动后处理后从数组中删除每个字段方法,我喜欢的方法:


如果您只想简单地打印数组,您甚至不需要循环浏览它:


更新:最近 bash &gt; = 4.4

bash 的较新版本中,您也可以使用命令 mapfile


此语法保留特殊的chars ,新线和空字段!

如果您不想包含空字段,则可以执行以下操作:


使用 mapfile ,您还可以跳过划界元素上声明数组并隐式“循环”,每个元素都在每个元素上调用一个函数:


(注意:格式字符串末端的 \ 0 ,如果您不在字符串末端关心空字段,或者它们不存在。)


但是您甚至可以使用 newline (mapfile的默认值)分隔符:


您可以使用&lt;&lt;&lt;&lt; ,并且在功能中包括一些处理,以删除newline IT添加:


基于 shell

如果您不能使用 bash 或如果您想编写可以在许多不同的外壳中使用的东西,那么您经常 use bashisms - 这包括我们在上述解决方案中使用的数组。

但是,我们不需要使用数组来循环浏览字符串的“元素”。许多壳中使用了一种语法,用于从 first 最后一个中删除字符串的子字符串。请注意,*是一个代表零或更多字符的通配符:(

,在任何解决方案中缺乏此方法是我写这个答案的主要原因;)


到目前为止 href =“ https://stackoverflow.com/posts/comments/47972612?noredirect=1”> score_under :

分别从字符串的 start end 中删除最短的匹配子字符串,和

## %% 删除最长可能的匹配子字符串。

使用上述语法,我们可以创建一种方法,通过在定界符之前或之后删除子字符串,从字符串中提取子字符串“元素”。

下面的代码块在 bash (包括mac os的 bash ), dash ksh yash> yash << /a>, zsh busybox 's ash :(

感谢 adam katz '使此循环变得更简单!)


为什么不剪切

剪切对于在大文件中提取列很有用,但是 forks 重复( var = $(echo ... | cut ... cut ...) )迅速过度杀伤!

这是一个正确的语法,在许多 posix shell 使用剪切,如 dougw << /a>:


比较执行时间


准备999个字段:


然后


使用 1 forks cut by field 1 forks >,对于少于1'000字段

\n'} # drop '\n' added on last field, by '<<<'

使用 mapfile ,您还可以跳过划界元素上声明数组并隐式“循环”,每个元素都在每个元素上调用一个函数:


(注意:格式字符串末端的 \ 0 ,如果您不在字符串末端关心空字段,或者它们不存在。)


但是您甚至可以使用 newline (mapfile的默认值)分隔符:


您可以使用&lt;&lt;&lt;&lt; ,并且在功能中包括一些处理,以删除newline IT添加:


基于 shell

如果您不能使用 bash 或如果您想编写可以在许多不同的外壳中使用的东西,那么您经常 use bashisms - 这包括我们在上述解决方案中使用的数组。

但是,我们不需要使用数组来循环浏览字符串的“元素”。许多壳中使用了一种语法,用于从 first 最后一个中删除字符串的子字符串。请注意,*是一个代表零或更多字符的通配符:(

,在任何解决方案中缺乏此方法是我写这个答案的主要原因;)


到目前为止 href =“ https://stackoverflow.com/posts/comments/47972612?noredirect=1”> score_under :

分别从字符串的 start end 中删除最短的匹配子字符串,和

## %% 删除最长可能的匹配子字符串。

使用上述语法,我们可以创建一种方法,通过在定界符之前或之后删除子字符串,从字符串中提取子字符串“元素”。

下面的代码块在 bash (包括mac os的 bash ), dash ksh yash> yash << /a>, zsh busybox 's ash :(

感谢 adam katz '使此循环变得更简单!)


为什么不剪切

剪切对于在大文件中提取列很有用,但是 forks 重复( var = $(echo ... | cut ... cut ...) )迅速过度杀伤!

这是一个正确的语法,在许多 posix shell 使用剪切,如 dougw << /a>:


比较执行时间


准备999个字段:


然后


使用 1 forks cut by field 1 forks >,对于少于1'000字段

\t\n'

我们可以看到,中的字符串已存储在名为 fields 的数组中,在半olons上分开:(


我们可以还使用声明-p :)


请注意,读取最快进行分割的方法,因为没有< em> forks 或调用外部资源。

定义数组后,您可以使用一个简单的循环来处理每个字段(或者,您现在定义的数组中的每个元素):


或者可以在使用移动后处理后从数组中删除每个字段方法,我喜欢的方法:


如果您只想简单地打印数组,您甚至不需要循环浏览它:


更新:最近 bash &gt; = 4.4

bash 的较新版本中,您也可以使用命令 mapfile


此语法保留特殊的chars ,新线和空字段!

如果您不想包含空字段,则可以执行以下操作:


使用 mapfile ,您还可以跳过划界元素上声明数组并隐式“循环”,每个元素都在每个元素上调用一个函数:


(注意:格式字符串末端的 \ 0 ,如果您不在字符串末端关心空字段,或者它们不存在。)


但是您甚至可以使用 newline (mapfile的默认值)分隔符:


您可以使用&lt;&lt;&lt;&lt; ,并且在功能中包括一些处理,以删除newline IT添加:


基于 shell

如果您不能使用 bash 或如果您想编写可以在许多不同的外壳中使用的东西,那么您经常 use bashisms - 这包括我们在上述解决方案中使用的数组。

但是,我们不需要使用数组来循环浏览字符串的“元素”。许多壳中使用了一种语法,用于从 first 最后一个中删除字符串的子字符串。请注意,*是一个代表零或更多字符的通配符:(

,在任何解决方案中缺乏此方法是我写这个答案的主要原因;)


到目前为止 href =“ https://stackoverflow.com/posts/comments/47972612?noredirect=1”> score_under :

分别从字符串的 start end 中删除最短的匹配子字符串,和

## %% 删除最长可能的匹配子字符串。

使用上述语法,我们可以创建一种方法,通过在定界符之前或之后删除子字符串,从字符串中提取子字符串“元素”。

下面的代码块在 bash (包括mac os的 bash ), dash ksh yash> yash << /a>, zsh busybox 's ash :(

感谢 adam katz '使此循环变得更简单!)


为什么不剪切

剪切对于在大文件中提取列很有用,但是 forks 重复( var = $(echo ... | cut ... cut ...) )迅速过度杀伤!

这是一个正确的语法,在许多 posix shell 使用剪切,如 dougw << /a>:


比较执行时间


准备999个字段:


然后


使用 1 forks cut by field 1 forks >,对于少于1'000字段

\n'}" -tc 1 -C myPubliMail # Seq: 0: Sending mail to '[email protected]', done. # Seq: 1: Sending mail to '[email protected]', done. # Seq: 2: Sending mail to 'Full Name <[email protected]>', done.

您可以使用&lt;&lt;&lt;&lt; ,并且在功能中包括一些处理,以删除newline IT添加:


基于 shell

如果您不能使用 bash 或如果您想编写可以在许多不同的外壳中使用的东西,那么您经常 use bashisms - 这包括我们在上述解决方案中使用的数组。

但是,我们不需要使用数组来循环浏览字符串的“元素”。许多壳中使用了一种语法,用于从 first 最后一个中删除字符串的子字符串。请注意,*是一个代表零或更多字符的通配符:(

,在任何解决方案中缺乏此方法是我写这个答案的主要原因;)


到目前为止 href =“ https://stackoverflow.com/posts/comments/47972612?noredirect=1”> score_under :

分别从字符串的 start end 中删除最短的匹配子字符串,和

## %% 删除最长可能的匹配子字符串。

使用上述语法,我们可以创建一种方法,通过在定界符之前或之后删除子字符串,从字符串中提取子字符串“元素”。

下面的代码块在 bash (包括mac os的 bash ), dash ksh yash> yash << /a>, zsh busybox 's ash :(

感谢 adam katz '使此循环变得更简单!)


为什么不剪切

剪切对于在大文件中提取列很有用,但是 forks 重复( var = $(echo ... | cut ... cut ...) )迅速过度杀伤!

这是一个正确的语法,在许多 posix shell 使用剪切,如 dougw << /a>:


比较执行时间


准备999个字段:


然后


使用 1 forks cut by field 1 forks >,对于少于1'000字段

\t\n'

我们可以看到,中的字符串已存储在名为 fields 的数组中,在半olons上分开:(


我们可以还使用声明-p :)


请注意,读取最快进行分割的方法,因为没有< em> forks 或调用外部资源。

定义数组后,您可以使用一个简单的循环来处理每个字段(或者,您现在定义的数组中的每个元素):


或者可以在使用移动后处理后从数组中删除每个字段方法,我喜欢的方法:


如果您只想简单地打印数组,您甚至不需要循环浏览它:


更新:最近 bash &gt; = 4.4

bash 的较新版本中,您也可以使用命令 mapfile


此语法保留特殊的chars ,新线和空字段!

如果您不想包含空字段,则可以执行以下操作:


使用 mapfile ,您还可以跳过划界元素上声明数组并隐式“循环”,每个元素都在每个元素上调用一个函数:


(注意:格式字符串末端的 \ 0 ,如果您不在字符串末端关心空字段,或者它们不存在。)


但是您甚至可以使用 newline (mapfile的默认值)分隔符:


您可以使用&lt;&lt;&lt;&lt; ,并且在功能中包括一些处理,以删除newline IT添加:


基于 shell

如果您不能使用 bash 或如果您想编写可以在许多不同的外壳中使用的东西,那么您经常 use bashisms - 这包括我们在上述解决方案中使用的数组。

但是,我们不需要使用数组来循环浏览字符串的“元素”。许多壳中使用了一种语法,用于从 first 最后一个中删除字符串的子字符串。请注意,*是一个代表零或更多字符的通配符:(

,在任何解决方案中缺乏此方法是我写这个答案的主要原因;)


到目前为止 href =“ https://stackoverflow.com/posts/comments/47972612?noredirect=1”> score_under :

分别从字符串的 start end 中删除最短的匹配子字符串,和

## %% 删除最长可能的匹配子字符串。

使用上述语法,我们可以创建一种方法,通过在定界符之前或之后删除子字符串,从字符串中提取子字符串“元素”。

下面的代码块在 bash (包括mac os的 bash ), dash ksh yash> yash << /a>, zsh busybox 's ash :(

感谢 adam katz '使此循环变得更简单!)


为什么不剪切

剪切对于在大文件中提取列很有用,但是 forks 重复( var = $(echo ... | cut ... cut ...) )迅速过度杀伤!

这是一个正确的语法,在许多 posix shell 使用剪切,如 dougw << /a>:


比较执行时间


准备999个字段:


然后


使用 1 forks cut by field 1 forks >,对于少于1'000字段

\n'} # drop '\n' added on last field, by '<<<'

使用 mapfile ,您还可以跳过划界元素上声明数组并隐式“循环”,每个元素都在每个元素上调用一个函数:


(注意:格式字符串末端的 \ 0 ,如果您不在字符串末端关心空字段,或者它们不存在。)


但是您甚至可以使用 newline (mapfile的默认值)分隔符:


您可以使用&lt;&lt;&lt;&lt; ,并且在功能中包括一些处理,以删除newline IT添加:


基于 shell

如果您不能使用 bash 或如果您想编写可以在许多不同的外壳中使用的东西,那么您经常 use bashisms - 这包括我们在上述解决方案中使用的数组。

但是,我们不需要使用数组来循环浏览字符串的“元素”。许多壳中使用了一种语法,用于从 first 最后一个中删除字符串的子字符串。请注意,*是一个代表零或更多字符的通配符:(

,在任何解决方案中缺乏此方法是我写这个答案的主要原因;)


到目前为止 href =“ https://stackoverflow.com/posts/comments/47972612?noredirect=1”> score_under :

分别从字符串的 start end 中删除最短的匹配子字符串,和

## %% 删除最长可能的匹配子字符串。

使用上述语法,我们可以创建一种方法,通过在定界符之前或之后删除子字符串,从字符串中提取子字符串“元素”。

下面的代码块在 bash (包括mac os的 bash ), dash ksh yash> yash << /a>, zsh busybox 's ash :(

感谢 adam katz '使此循环变得更简单!)


为什么不剪切

剪切对于在大文件中提取列很有用,但是 forks 重复( var = $(echo ... | cut ... cut ...) )迅速过度杀伤!

这是一个正确的语法,在许多 posix shell 使用剪切,如 dougw << /a>:


比较执行时间


准备999个字段:


然后


使用 1 forks cut by field 1 forks >,对于少于1'000字段

\t\n'

我们可以看到,中的字符串已存储在名为 fields 的数组中,在半olons上分开:(


我们可以还使用声明-p :)


请注意,读取最快进行分割的方法,因为没有< em> forks 或调用外部资源。

定义数组后,您可以使用一个简单的循环来处理每个字段(或者,您现在定义的数组中的每个元素):


或者可以在使用移动后处理后从数组中删除每个字段方法,我喜欢的方法:


如果您只想简单地打印数组,您甚至不需要循环浏览它:


更新:最近 bash &gt; = 4.4

bash 的较新版本中,您也可以使用命令 mapfile


此语法保留特殊的chars ,新线和空字段!

如果您不想包含空字段,则可以执行以下操作:


使用 mapfile ,您还可以跳过划界元素上声明数组并隐式“循环”,每个元素都在每个元素上调用一个函数:


(注意:格式字符串末端的 \ 0 ,如果您不在字符串末端关心空字段,或者它们不存在。)


但是您甚至可以使用 newline (mapfile的默认值)分隔符:


您可以使用&lt;&lt;&lt;&lt; ,并且在功能中包括一些处理,以删除newline IT添加:


基于 shell

如果您不能使用 bash 或如果您想编写可以在许多不同的外壳中使用的东西,那么您经常 use bashisms - 这包括我们在上述解决方案中使用的数组。

但是,我们不需要使用数组来循环浏览字符串的“元素”。许多壳中使用了一种语法,用于从 first 最后一个中删除字符串的子字符串。请注意,*是一个代表零或更多字符的通配符:(

,在任何解决方案中缺乏此方法是我写这个答案的主要原因;)


到目前为止 href =“ https://stackoverflow.com/posts/comments/47972612?noredirect=1”> score_under :

分别从字符串的 start end 中删除最短的匹配子字符串,和

## %% 删除最长可能的匹配子字符串。

使用上述语法,我们可以创建一种方法,通过在定界符之前或之后删除子字符串,从字符串中提取子字符串“元素”。

下面的代码块在 bash (包括mac os的 bash ), dash ksh yash> yash << /a>, zsh busybox 's ash :(

感谢 adam katz '使此循环变得更简单!)


为什么不剪切

剪切对于在大文件中提取列很有用,但是 forks 重复( var = $(echo ... | cut ... cut ...) )迅速过度杀伤!

这是一个正确的语法,在许多 posix shell 使用剪切,如 dougw << /a>:


比较执行时间


准备999个字段:


然后


使用 1 forks cut by field 1 forks >,对于少于1'000字段

\n'}" -tc 1 -C iterMF }

准备999个字段:


然后


使用 1 forks cut by field 1 forks >,对于少于1'000字段

\t\n'

我们可以看到,中的字符串已存储在名为 fields 的数组中,在半olons上分开:(


我们可以还使用声明-p :)


请注意,读取最快进行分割的方法,因为没有< em> forks 或调用外部资源。

定义数组后,您可以使用一个简单的循环来处理每个字段(或者,您现在定义的数组中的每个元素):


或者可以在使用移动后处理后从数组中删除每个字段方法,我喜欢的方法:


如果您只想简单地打印数组,您甚至不需要循环浏览它:


更新:最近 bash &gt; = 4.4

bash 的较新版本中,您也可以使用命令 mapfile


此语法保留特殊的chars ,新线和空字段!

如果您不想包含空字段,则可以执行以下操作:


使用 mapfile ,您还可以跳过划界元素上声明数组并隐式“循环”,每个元素都在每个元素上调用一个函数:


(注意:格式字符串末端的 \ 0 ,如果您不在字符串末端关心空字段,或者它们不存在。)


但是您甚至可以使用 newline (mapfile的默认值)分隔符:


您可以使用&lt;&lt;&lt;&lt; ,并且在功能中包括一些处理,以删除newline IT添加:


基于 shell

如果您不能使用 bash 或如果您想编写可以在许多不同的外壳中使用的东西,那么您经常 use bashisms - 这包括我们在上述解决方案中使用的数组。

但是,我们不需要使用数组来循环浏览字符串的“元素”。许多壳中使用了一种语法,用于从 first 最后一个中删除字符串的子字符串。请注意,*是一个代表零或更多字符的通配符:(

,在任何解决方案中缺乏此方法是我写这个答案的主要原因;)


到目前为止 href =“ https://stackoverflow.com/posts/comments/47972612?noredirect=1”> score_under :

分别从字符串的 start end 中删除最短的匹配子字符串,和

## %% 删除最长可能的匹配子字符串。

使用上述语法,我们可以创建一种方法,通过在定界符之前或之后删除子字符串,从字符串中提取子字符串“元素”。

下面的代码块在 bash (包括mac os的 bash ), dash ksh yash> yash << /a>, zsh busybox 's ash :(

感谢 adam katz '使此循环变得更简单!)


为什么不剪切

剪切对于在大文件中提取列很有用,但是 forks 重复( var = $(echo ... | cut ... cut ...) )迅速过度杀伤!

这是一个正确的语法,在许多 posix shell 使用剪切,如 dougw << /a>:


比较执行时间


准备999个字段:


然后


使用 1 forks cut by field 1 forks >,对于少于1'000字段

\n'} # drop '\n' added on last field, by '<<<'

使用 mapfile ,您还可以跳过划界元素上声明数组并隐式“循环”,每个元素都在每个元素上调用一个函数:


(注意:格式字符串末端的 \ 0 ,如果您不在字符串末端关心空字段,或者它们不存在。)


但是您甚至可以使用 newline (mapfile的默认值)分隔符:


您可以使用&lt;&lt;&lt;&lt; ,并且在功能中包括一些处理,以删除newline IT添加:


基于 shell

如果您不能使用 bash 或如果您想编写可以在许多不同的外壳中使用的东西,那么您经常 use bashisms - 这包括我们在上述解决方案中使用的数组。

但是,我们不需要使用数组来循环浏览字符串的“元素”。许多壳中使用了一种语法,用于从 first 最后一个中删除字符串的子字符串。请注意,*是一个代表零或更多字符的通配符:(

,在任何解决方案中缺乏此方法是我写这个答案的主要原因;)


到目前为止 href =“ https://stackoverflow.com/posts/comments/47972612?noredirect=1”> score_under :

分别从字符串的 start end 中删除最短的匹配子字符串,和

## %% 删除最长可能的匹配子字符串。

使用上述语法,我们可以创建一种方法,通过在定界符之前或之后删除子字符串,从字符串中提取子字符串“元素”。

下面的代码块在 bash (包括mac os的 bash ), dash ksh yash> yash << /a>, zsh busybox 's ash :(

感谢 adam katz '使此循环变得更简单!)


为什么不剪切

剪切对于在大文件中提取列很有用,但是 forks 重复( var = $(echo ... | cut ... cut ...) )迅速过度杀伤!

这是一个正确的语法,在许多 posix shell 使用剪切,如 dougw << /a>:


比较执行时间


准备999个字段:


然后


使用 1 forks cut by field 1 forks >,对于少于1'000字段

\t\n'

我们可以看到,中的字符串已存储在名为 fields 的数组中,在半olons上分开:(


我们可以还使用声明-p :)


请注意,读取最快进行分割的方法,因为没有< em> forks 或调用外部资源。

定义数组后,您可以使用一个简单的循环来处理每个字段(或者,您现在定义的数组中的每个元素):


或者可以在使用移动后处理后从数组中删除每个字段方法,我喜欢的方法:


如果您只想简单地打印数组,您甚至不需要循环浏览它:


更新:最近 bash &gt; = 4.4

bash 的较新版本中,您也可以使用命令 mapfile


此语法保留特殊的chars ,新线和空字段!

如果您不想包含空字段,则可以执行以下操作:


使用 mapfile ,您还可以跳过划界元素上声明数组并隐式“循环”,每个元素都在每个元素上调用一个函数:


(注意:格式字符串末端的 \ 0 ,如果您不在字符串末端关心空字段,或者它们不存在。)


但是您甚至可以使用 newline (mapfile的默认值)分隔符:


您可以使用&lt;&lt;&lt;&lt; ,并且在功能中包括一些处理,以删除newline IT添加:


基于 shell

如果您不能使用 bash 或如果您想编写可以在许多不同的外壳中使用的东西,那么您经常 use bashisms - 这包括我们在上述解决方案中使用的数组。

但是,我们不需要使用数组来循环浏览字符串的“元素”。许多壳中使用了一种语法,用于从 first 最后一个中删除字符串的子字符串。请注意,*是一个代表零或更多字符的通配符:(

,在任何解决方案中缺乏此方法是我写这个答案的主要原因;)


到目前为止 href =“ https://stackoverflow.com/posts/comments/47972612?noredirect=1”> score_under :

分别从字符串的 start end 中删除最短的匹配子字符串,和

## %% 删除最长可能的匹配子字符串。

使用上述语法,我们可以创建一种方法,通过在定界符之前或之后删除子字符串,从字符串中提取子字符串“元素”。

下面的代码块在 bash (包括mac os的 bash ), dash ksh yash> yash << /a>, zsh busybox 's ash :(

感谢 adam katz '使此循环变得更简单!)


为什么不剪切

剪切对于在大文件中提取列很有用,但是 forks 重复( var = $(echo ... | cut ... cut ...) )迅速过度杀伤!

这是一个正确的语法,在许多 posix shell 使用剪切,如 dougw << /a>:


比较执行时间


准备999个字段:


然后


使用 1 forks cut by field 1 forks >,对于少于1'000字段

\n'}" -tc 1 -C myPubliMail # Seq: 0: Sending mail to '[email protected]', done. # Seq: 1: Sending mail to '[email protected]', done. # Seq: 2: Sending mail to 'Full Name <[email protected]>', done.

您可以使用&lt;&lt;&lt;&lt; ,并且在功能中包括一些处理,以删除newline IT添加:


基于 shell

如果您不能使用 bash 或如果您想编写可以在许多不同的外壳中使用的东西,那么您经常 use bashisms - 这包括我们在上述解决方案中使用的数组。

但是,我们不需要使用数组来循环浏览字符串的“元素”。许多壳中使用了一种语法,用于从 first 最后一个中删除字符串的子字符串。请注意,*是一个代表零或更多字符的通配符:(

,在任何解决方案中缺乏此方法是我写这个答案的主要原因;)


到目前为止 href =“ https://stackoverflow.com/posts/comments/47972612?noredirect=1”> score_under :

分别从字符串的 start end 中删除最短的匹配子字符串,和

## %% 删除最长可能的匹配子字符串。

使用上述语法,我们可以创建一种方法,通过在定界符之前或之后删除子字符串,从字符串中提取子字符串“元素”。

下面的代码块在 bash (包括mac os的 bash ), dash ksh yash> yash << /a>, zsh busybox 's ash :(

感谢 adam katz '使此循环变得更简单!)


为什么不剪切

剪切对于在大文件中提取列很有用,但是 forks 重复( var = $(echo ... | cut ... cut ...) )迅速过度杀伤!

这是一个正确的语法,在许多 posix shell 使用剪切,如 dougw << /a>:


比较执行时间


准备999个字段:


然后


使用 1 forks cut by field 1 forks >,对于少于1'000字段

\t\n'

我们可以看到,中的字符串已存储在名为 fields 的数组中,在半olons上分开:(


我们可以还使用声明-p :)


请注意,读取最快进行分割的方法,因为没有< em> forks 或调用外部资源。

定义数组后,您可以使用一个简单的循环来处理每个字段(或者,您现在定义的数组中的每个元素):


或者可以在使用移动后处理后从数组中删除每个字段方法,我喜欢的方法:


如果您只想简单地打印数组,您甚至不需要循环浏览它:


更新:最近 bash &gt; = 4.4

bash 的较新版本中,您也可以使用命令 mapfile


此语法保留特殊的chars ,新线和空字段!

如果您不想包含空字段,则可以执行以下操作:


使用 mapfile ,您还可以跳过划界元素上声明数组并隐式“循环”,每个元素都在每个元素上调用一个函数:


(注意:格式字符串末端的 \ 0 ,如果您不在字符串末端关心空字段,或者它们不存在。)


但是您甚至可以使用 newline (mapfile的默认值)分隔符:


您可以使用&lt;&lt;&lt;&lt; ,并且在功能中包括一些处理,以删除newline IT添加:


基于 shell

如果您不能使用 bash 或如果您想编写可以在许多不同的外壳中使用的东西,那么您经常 use bashisms - 这包括我们在上述解决方案中使用的数组。

但是,我们不需要使用数组来循环浏览字符串的“元素”。许多壳中使用了一种语法,用于从 first 最后一个中删除字符串的子字符串。请注意,*是一个代表零或更多字符的通配符:(

,在任何解决方案中缺乏此方法是我写这个答案的主要原因;)


到目前为止 href =“ https://stackoverflow.com/posts/comments/47972612?noredirect=1”> score_under :

分别从字符串的 start end 中删除最短的匹配子字符串,和

## %% 删除最长可能的匹配子字符串。

使用上述语法,我们可以创建一种方法,通过在定界符之前或之后删除子字符串,从字符串中提取子字符串“元素”。

下面的代码块在 bash (包括mac os的 bash ), dash ksh yash> yash << /a>, zsh busybox 's ash :(

感谢 adam katz '使此循环变得更简单!)


为什么不剪切

剪切对于在大文件中提取列很有用,但是 forks 重复( var = $(echo ... | cut ... cut ...) )迅速过度杀伤!

这是一个正确的语法,在许多 posix shell 使用剪切,如 dougw << /a>:


比较执行时间


准备999个字段:


然后


使用 1 forks cut by field 1 forks >,对于少于1'000字段

\n'} # drop '\n' added on last field, by '<<<'

使用 mapfile ,您还可以跳过划界元素上声明数组并隐式“循环”,每个元素都在每个元素上调用一个函数:


(注意:格式字符串末端的 \ 0 ,如果您不在字符串末端关心空字段,或者它们不存在。)


但是您甚至可以使用 newline (mapfile的默认值)分隔符:


您可以使用&lt;&lt;&lt;&lt; ,并且在功能中包括一些处理,以删除newline IT添加:


基于 shell

如果您不能使用 bash 或如果您想编写可以在许多不同的外壳中使用的东西,那么您经常 use bashisms - 这包括我们在上述解决方案中使用的数组。

但是,我们不需要使用数组来循环浏览字符串的“元素”。许多壳中使用了一种语法,用于从 first 最后一个中删除字符串的子字符串。请注意,*是一个代表零或更多字符的通配符:(

,在任何解决方案中缺乏此方法是我写这个答案的主要原因;)


到目前为止 href =“ https://stackoverflow.com/posts/comments/47972612?noredirect=1”> score_under :

分别从字符串的 start end 中删除最短的匹配子字符串,和

## %% 删除最长可能的匹配子字符串。

使用上述语法,我们可以创建一种方法,通过在定界符之前或之后删除子字符串,从字符串中提取子字符串“元素”。

下面的代码块在 bash (包括mac os的 bash ), dash ksh yash> yash << /a>, zsh busybox 's ash :(

感谢 adam katz '使此循环变得更简单!)


为什么不剪切

剪切对于在大文件中提取列很有用,但是 forks 重复( var = $(echo ... | cut ... cut ...) )迅速过度杀伤!

这是一个正确的语法,在许多 posix shell 使用剪切,如 dougw << /a>:


比较执行时间


准备999个字段:


然后


使用 1 forks cut by field 1 forks >,对于少于1'000字段

\t\n'

我们可以看到,中的字符串已存储在名为 fields 的数组中,在半olons上分开:(


我们可以还使用声明-p :)


请注意,读取最快进行分割的方法,因为没有< em> forks 或调用外部资源。

定义数组后,您可以使用一个简单的循环来处理每个字段(或者,您现在定义的数组中的每个元素):


或者可以在使用移动后处理后从数组中删除每个字段方法,我喜欢的方法:


如果您只想简单地打印数组,您甚至不需要循环浏览它:


更新:最近 bash &gt; = 4.4

bash 的较新版本中,您也可以使用命令 mapfile


此语法保留特殊的chars ,新线和空字段!

如果您不想包含空字段,则可以执行以下操作:


使用 mapfile ,您还可以跳过划界元素上声明数组并隐式“循环”,每个元素都在每个元素上调用一个函数:


(注意:格式字符串末端的 \ 0 ,如果您不在字符串末端关心空字段,或者它们不存在。)


但是您甚至可以使用 newline (mapfile的默认值)分隔符:


您可以使用&lt;&lt;&lt;&lt; ,并且在功能中包括一些处理,以删除newline IT添加:


基于 shell

如果您不能使用 bash 或如果您想编写可以在许多不同的外壳中使用的东西,那么您经常 use bashisms - 这包括我们在上述解决方案中使用的数组。

但是,我们不需要使用数组来循环浏览字符串的“元素”。许多壳中使用了一种语法,用于从 first 最后一个中删除字符串的子字符串。请注意,*是一个代表零或更多字符的通配符:(

,在任何解决方案中缺乏此方法是我写这个答案的主要原因;)


到目前为止 href =“ https://stackoverflow.com/posts/comments/47972612?noredirect=1”> score_under :

分别从字符串的 start end 中删除最短的匹配子字符串,和

## %% 删除最长可能的匹配子字符串。

使用上述语法,我们可以创建一种方法,通过在定界符之前或之后删除子字符串,从字符串中提取子字符串“元素”。

下面的代码块在 bash (包括mac os的 bash ), dash ksh yash> yash << /a>, zsh busybox 's ash :(

感谢 adam katz '使此循环变得更简单!)


为什么不剪切

剪切对于在大文件中提取列很有用,但是 forks 重复( var = $(echo ... | cut ... cut ...) )迅速过度杀伤!

这是一个正确的语法,在许多 posix shell 使用剪切,如 dougw << /a>:


比较执行时间


准备999个字段:


然后


使用 1 forks cut by field 1 forks >,对于少于1'000字段

\n'}" printf "Seq: %6d: Sending mail to '%s'..." $seq "$dest" # mail -s "This is not a spam..." "$dest" </path/to/body printf "\e[3D, done.\n" } mapfile <<<"$IN" -td \; -c 1 -C myPubliMail # Renders the same output: # Seq: 0: Sending mail to '[email protected]', done. # Seq: 1: Sending mail to '[email protected]', done. # Seq: 2: Sending mail to 'Full Name <[email protected]>', done.

基于 shell

如果您不能使用 bash 或如果您想编写可以在许多不同的外壳中使用的东西,那么您经常 use bashisms - 这包括我们在上述解决方案中使用的数组。

但是,我们不需要使用数组来循环浏览字符串的“元素”。许多壳中使用了一种语法,用于从 first 最后一个中删除字符串的子字符串。请注意,*是一个代表零或更多字符的通配符:(

,在任何解决方案中缺乏此方法是我写这个答案的主要原因;)


到目前为止 href =“ https://stackoverflow.com/posts/comments/47972612?noredirect=1”> score_under :

分别从字符串的 start end 中删除最短的匹配子字符串,和

## %% 删除最长可能的匹配子字符串。

使用上述语法,我们可以创建一种方法,通过在定界符之前或之后删除子字符串,从字符串中提取子字符串“元素”。

下面的代码块在 bash (包括mac os的 bash ), dash ksh yash> yash << /a>, zsh busybox 's ash :(

感谢 adam katz '使此循环变得更简单!)


为什么不剪切

剪切对于在大文件中提取列很有用,但是 forks 重复( var = $(echo ... | cut ... cut ...) )迅速过度杀伤!

这是一个正确的语法,在许多 posix shell 使用剪切,如 dougw << /a>:


比较执行时间


准备999个字段:


然后


使用 1 forks cut by field 1 forks >,对于少于1'000字段

\t\n'

我们可以看到,中的字符串已存储在名为 fields 的数组中,在半olons上分开:(


我们可以还使用声明-p :)


请注意,读取最快进行分割的方法,因为没有< em> forks 或调用外部资源。

定义数组后,您可以使用一个简单的循环来处理每个字段(或者,您现在定义的数组中的每个元素):


或者可以在使用移动后处理后从数组中删除每个字段方法,我喜欢的方法:


如果您只想简单地打印数组,您甚至不需要循环浏览它:


更新:最近 bash &gt; = 4.4

bash 的较新版本中,您也可以使用命令 mapfile


此语法保留特殊的chars ,新线和空字段!

如果您不想包含空字段,则可以执行以下操作:


使用 mapfile ,您还可以跳过划界元素上声明数组并隐式“循环”,每个元素都在每个元素上调用一个函数:


(注意:格式字符串末端的 \ 0 ,如果您不在字符串末端关心空字段,或者它们不存在。)


但是您甚至可以使用 newline (mapfile的默认值)分隔符:


您可以使用&lt;&lt;&lt;&lt; ,并且在功能中包括一些处理,以删除newline IT添加:


基于 shell

如果您不能使用 bash 或如果您想编写可以在许多不同的外壳中使用的东西,那么您经常 use bashisms - 这包括我们在上述解决方案中使用的数组。

但是,我们不需要使用数组来循环浏览字符串的“元素”。许多壳中使用了一种语法,用于从 first 最后一个中删除字符串的子字符串。请注意,*是一个代表零或更多字符的通配符:(

,在任何解决方案中缺乏此方法是我写这个答案的主要原因;)


到目前为止 href =“ https://stackoverflow.com/posts/comments/47972612?noredirect=1”> score_under :

分别从字符串的 start end 中删除最短的匹配子字符串,和

## %% 删除最长可能的匹配子字符串。

使用上述语法,我们可以创建一种方法,通过在定界符之前或之后删除子字符串,从字符串中提取子字符串“元素”。

下面的代码块在 bash (包括mac os的 bash ), dash ksh yash> yash << /a>, zsh busybox 's ash :(

感谢 adam katz '使此循环变得更简单!)


为什么不剪切

剪切对于在大文件中提取列很有用,但是 forks 重复( var = $(echo ... | cut ... cut ...) )迅速过度杀伤!

这是一个正确的语法,在许多 posix shell 使用剪切,如 dougw << /a>:


比较执行时间


准备999个字段:


然后


使用 1 forks cut by field 1 forks >,对于少于1'000字段

\n'} # drop '\n' added on last field, by '<<<'

使用 mapfile ,您还可以跳过划界元素上声明数组并隐式“循环”,每个元素都在每个元素上调用一个函数:


(注意:格式字符串末端的 \ 0 ,如果您不在字符串末端关心空字段,或者它们不存在。)


但是您甚至可以使用 newline (mapfile的默认值)分隔符:


您可以使用&lt;&lt;&lt;&lt; ,并且在功能中包括一些处理,以删除newline IT添加:


基于 shell

如果您不能使用 bash 或如果您想编写可以在许多不同的外壳中使用的东西,那么您经常 use bashisms - 这包括我们在上述解决方案中使用的数组。

但是,我们不需要使用数组来循环浏览字符串的“元素”。许多壳中使用了一种语法,用于从 first 最后一个中删除字符串的子字符串。请注意,*是一个代表零或更多字符的通配符:(

,在任何解决方案中缺乏此方法是我写这个答案的主要原因;)


到目前为止 href =“ https://stackoverflow.com/posts/comments/47972612?noredirect=1”> score_under :

分别从字符串的 start end 中删除最短的匹配子字符串,和

## %% 删除最长可能的匹配子字符串。

使用上述语法,我们可以创建一种方法,通过在定界符之前或之后删除子字符串,从字符串中提取子字符串“元素”。

下面的代码块在 bash (包括mac os的 bash ), dash ksh yash> yash << /a>, zsh busybox 's ash :(

感谢 adam katz '使此循环变得更简单!)


为什么不剪切

剪切对于在大文件中提取列很有用,但是 forks 重复( var = $(echo ... | cut ... cut ...) )迅速过度杀伤!

这是一个正确的语法,在许多 posix shell 使用剪切,如 dougw << /a>:


比较执行时间


准备999个字段:


然后


使用 1 forks cut by field 1 forks >,对于少于1'000字段

\t\n'

我们可以看到,中的字符串已存储在名为 fields 的数组中,在半olons上分开:(


我们可以还使用声明-p :)


请注意,读取最快进行分割的方法,因为没有< em> forks 或调用外部资源。

定义数组后,您可以使用一个简单的循环来处理每个字段(或者,您现在定义的数组中的每个元素):


或者可以在使用移动后处理后从数组中删除每个字段方法,我喜欢的方法:


如果您只想简单地打印数组,您甚至不需要循环浏览它:


更新:最近 bash &gt; = 4.4

bash 的较新版本中,您也可以使用命令 mapfile


此语法保留特殊的chars ,新线和空字段!

如果您不想包含空字段,则可以执行以下操作:


使用 mapfile ,您还可以跳过划界元素上声明数组并隐式“循环”,每个元素都在每个元素上调用一个函数:


(注意:格式字符串末端的 \ 0 ,如果您不在字符串末端关心空字段,或者它们不存在。)


但是您甚至可以使用 newline (mapfile的默认值)分隔符:


您可以使用&lt;&lt;&lt;&lt; ,并且在功能中包括一些处理,以删除newline IT添加:


基于 shell

如果您不能使用 bash 或如果您想编写可以在许多不同的外壳中使用的东西,那么您经常 use bashisms - 这包括我们在上述解决方案中使用的数组。

但是,我们不需要使用数组来循环浏览字符串的“元素”。许多壳中使用了一种语法,用于从 first 最后一个中删除字符串的子字符串。请注意,*是一个代表零或更多字符的通配符:(

,在任何解决方案中缺乏此方法是我写这个答案的主要原因;)


到目前为止 href =“ https://stackoverflow.com/posts/comments/47972612?noredirect=1”> score_under :

分别从字符串的 start end 中删除最短的匹配子字符串,和

## %% 删除最长可能的匹配子字符串。

使用上述语法,我们可以创建一种方法,通过在定界符之前或之后删除子字符串,从字符串中提取子字符串“元素”。

下面的代码块在 bash (包括mac os的 bash ), dash ksh yash> yash << /a>, zsh busybox 's ash :(

感谢 adam katz '使此循环变得更简单!)


为什么不剪切

剪切对于在大文件中提取列很有用,但是 forks 重复( var = $(echo ... | cut ... cut ...) )迅速过度杀伤!

这是一个正确的语法,在许多 posix shell 使用剪切,如 dougw << /a>:


比较执行时间


准备999个字段:


然后


使用 1 forks cut by field 1 forks >,对于少于1'000字段

\n'}" -tc 1 -C myPubliMail # Seq: 0: Sending mail to '[email protected]', done. # Seq: 1: Sending mail to '[email protected]', done. # Seq: 2: Sending mail to 'Full Name <[email protected]>', done.

您可以使用&lt;&lt;&lt;&lt; ,并且在功能中包括一些处理,以删除newline IT添加:


基于 shell

如果您不能使用 bash 或如果您想编写可以在许多不同的外壳中使用的东西,那么您经常 use bashisms - 这包括我们在上述解决方案中使用的数组。

但是,我们不需要使用数组来循环浏览字符串的“元素”。许多壳中使用了一种语法,用于从 first 最后一个中删除字符串的子字符串。请注意,*是一个代表零或更多字符的通配符:(

,在任何解决方案中缺乏此方法是我写这个答案的主要原因;)


到目前为止 href =“ https://stackoverflow.com/posts/comments/47972612?noredirect=1”> score_under :

分别从字符串的 start end 中删除最短的匹配子字符串,和

## %% 删除最长可能的匹配子字符串。

使用上述语法,我们可以创建一种方法,通过在定界符之前或之后删除子字符串,从字符串中提取子字符串“元素”。

下面的代码块在 bash (包括mac os的 bash ), dash ksh yash> yash << /a>, zsh busybox 's ash :(

感谢 adam katz '使此循环变得更简单!)


为什么不剪切

剪切对于在大文件中提取列很有用,但是 forks 重复( var = $(echo ... | cut ... cut ...) )迅速过度杀伤!

这是一个正确的语法,在许多 posix shell 使用剪切,如 dougw << /a>:


比较执行时间


准备999个字段:


然后


使用 1 forks cut by field 1 forks >,对于少于1'000字段

\t\n'

我们可以看到,中的字符串已存储在名为 fields 的数组中,在半olons上分开:(


我们可以还使用声明-p :)


请注意,读取最快进行分割的方法,因为没有< em> forks 或调用外部资源。

定义数组后,您可以使用一个简单的循环来处理每个字段(或者,您现在定义的数组中的每个元素):


或者可以在使用移动后处理后从数组中删除每个字段方法,我喜欢的方法:


如果您只想简单地打印数组,您甚至不需要循环浏览它:


更新:最近 bash &gt; = 4.4

bash 的较新版本中,您也可以使用命令 mapfile


此语法保留特殊的chars ,新线和空字段!

如果您不想包含空字段,则可以执行以下操作:


使用 mapfile ,您还可以跳过划界元素上声明数组并隐式“循环”,每个元素都在每个元素上调用一个函数:


(注意:格式字符串末端的 \ 0 ,如果您不在字符串末端关心空字段,或者它们不存在。)


但是您甚至可以使用 newline (mapfile的默认值)分隔符:


您可以使用&lt;&lt;&lt;&lt; ,并且在功能中包括一些处理,以删除newline IT添加:


基于 shell

如果您不能使用 bash 或如果您想编写可以在许多不同的外壳中使用的东西,那么您经常 use bashisms - 这包括我们在上述解决方案中使用的数组。

但是,我们不需要使用数组来循环浏览字符串的“元素”。许多壳中使用了一种语法,用于从 first 最后一个中删除字符串的子字符串。请注意,*是一个代表零或更多字符的通配符:(

,在任何解决方案中缺乏此方法是我写这个答案的主要原因;)


到目前为止 href =“ https://stackoverflow.com/posts/comments/47972612?noredirect=1”> score_under :

分别从字符串的 start end 中删除最短的匹配子字符串,和

## %% 删除最长可能的匹配子字符串。

使用上述语法,我们可以创建一种方法,通过在定界符之前或之后删除子字符串,从字符串中提取子字符串“元素”。

下面的代码块在 bash (包括mac os的 bash ), dash ksh yash> yash << /a>, zsh busybox 's ash :(

感谢 adam katz '使此循环变得更简单!)


为什么不剪切

剪切对于在大文件中提取列很有用,但是 forks 重复( var = $(echo ... | cut ... cut ...) )迅速过度杀伤!

这是一个正确的语法,在许多 posix shell 使用剪切,如 dougw << /a>:


比较执行时间


准备999个字段:


然后


使用 1 forks cut by field 1 forks >,对于少于1'000字段

\n'} # drop '\n' added on last field, by '<<<'

使用 mapfile ,您还可以跳过划界元素上声明数组并隐式“循环”,每个元素都在每个元素上调用一个函数:


(注意:格式字符串末端的 \ 0 ,如果您不在字符串末端关心空字段,或者它们不存在。)


但是您甚至可以使用 newline (mapfile的默认值)分隔符:


您可以使用&lt;&lt;&lt;&lt; ,并且在功能中包括一些处理,以删除newline IT添加:


基于 shell

如果您不能使用 bash 或如果您想编写可以在许多不同的外壳中使用的东西,那么您经常 use bashisms - 这包括我们在上述解决方案中使用的数组。

但是,我们不需要使用数组来循环浏览字符串的“元素”。许多壳中使用了一种语法,用于从 first 最后一个中删除字符串的子字符串。请注意,*是一个代表零或更多字符的通配符:(

,在任何解决方案中缺乏此方法是我写这个答案的主要原因;)


到目前为止 href =“ https://stackoverflow.com/posts/comments/47972612?noredirect=1”> score_under :

分别从字符串的 start end 中删除最短的匹配子字符串,和

## %% 删除最长可能的匹配子字符串。

使用上述语法,我们可以创建一种方法,通过在定界符之前或之后删除子字符串,从字符串中提取子字符串“元素”。

下面的代码块在 bash (包括mac os的 bash ), dash ksh yash> yash << /a>, zsh busybox 's ash :(

感谢 adam katz '使此循环变得更简单!)


为什么不剪切

剪切对于在大文件中提取列很有用,但是 forks 重复( var = $(echo ... | cut ... cut ...) )迅速过度杀伤!

这是一个正确的语法,在许多 posix shell 使用剪切,如 dougw << /a>:


比较执行时间


准备999个字段:


然后


使用 1 forks cut by field 1 forks >,对于少于1'000字段

\t\n'

我们可以看到,中的字符串已存储在名为 fields 的数组中,在半olons上分开:(


我们可以还使用声明-p :)


请注意,读取最快进行分割的方法,因为没有< em> forks 或调用外部资源。

定义数组后,您可以使用一个简单的循环来处理每个字段(或者,您现在定义的数组中的每个元素):


或者可以在使用移动后处理后从数组中删除每个字段方法,我喜欢的方法:


如果您只想简单地打印数组,您甚至不需要循环浏览它:


更新:最近 bash &gt; = 4.4

bash 的较新版本中,您也可以使用命令 mapfile


此语法保留特殊的chars ,新线和空字段!

如果您不想包含空字段,则可以执行以下操作:


使用 mapfile ,您还可以跳过划界元素上声明数组并隐式“循环”,每个元素都在每个元素上调用一个函数:


(注意:格式字符串末端的 \ 0 ,如果您不在字符串末端关心空字段,或者它们不存在。)


但是您甚至可以使用 newline (mapfile的默认值)分隔符:


您可以使用&lt;&lt;&lt;&lt; ,并且在功能中包括一些处理,以删除newline IT添加:


基于 shell

如果您不能使用 bash 或如果您想编写可以在许多不同的外壳中使用的东西,那么您经常 use bashisms - 这包括我们在上述解决方案中使用的数组。

但是,我们不需要使用数组来循环浏览字符串的“元素”。许多壳中使用了一种语法,用于从 first 最后一个中删除字符串的子字符串。请注意,*是一个代表零或更多字符的通配符:(

,在任何解决方案中缺乏此方法是我写这个答案的主要原因;)


到目前为止 href =“ https://stackoverflow.com/posts/comments/47972612?noredirect=1”> score_under :

分别从字符串的 start end 中删除最短的匹配子字符串,和

## %% 删除最长可能的匹配子字符串。

使用上述语法,我们可以创建一种方法,通过在定界符之前或之后删除子字符串,从字符串中提取子字符串“元素”。

下面的代码块在 bash (包括mac os的 bash ), dash ksh yash> yash << /a>, zsh busybox 's ash :(

感谢 adam katz '使此循环变得更简单!)


为什么不剪切

剪切对于在大文件中提取列很有用,但是 forks 重复( var = $(echo ... | cut ... cut ...) )迅速过度杀伤!

这是一个正确的语法,在许多 posix shell 使用剪切,如 dougw << /a>:


比较执行时间


准备999个字段:


然后


使用 1 forks cut by field 1 forks >,对于少于1'000字段

Compatible answer

There are a lot of different ways to do this in .

However, it's important to first note that bash has many special features (so-called bashisms) that won't work in any other .

In particular, arrays, associative arrays, and pattern substitution, which are used in the solutions in this post as well as others in the thread, are bashisms and may not work under other shells that many people use.

For instance: on my Debian GNU/Linux, there is a standard shell called ; I know many people who like to use another shell called ; and there is also a special tool called with his own shell interpreter ().

For compatible answer, go to last part of this answer!

Requested string

The string to be split in the above question is:

IN="[email protected];[email protected]"

I will use a modified version of this string to ensure that my solution is robust to strings containing whitespace, which could break other solutions:

IN="[email protected];[email protected];Full Name <[email protected]>"

Split string based on delimiter in (version >=4.2)

In pure bash, we can create an array with elements split by a temporary value for IFS (the input field separator). The IFS, among other things, tells bash which character(s) it should treat as a delimiter between elements when defining an array:

IN="[email protected];[email protected];Full Name <[email protected]>"

# save original IFS value so we can restore it later
oIFS="$IFS"
IFS=";"
declare -a fields=($IN)
IFS="$oIFS"
unset oIFS

In newer versions of bash, prefixing a command with an IFS definition changes the IFS for that command only and resets it to the previous value immediately afterwards. This means we can do the above in just one line:

IFS=\; read -ra fields <<<"$IN"
# after this command, the IFS resets back to its previous value (here, the default):
set | grep ^IFS=
# IFS=

We can see that the string IN has been stored into an array named fields, split on the semicolons:

set | grep ^fields=\\\|^IN=
# fields=([0]="[email protected]" [1]="[email protected]" [2]="Full Name <[email protected]>")
# IN='[email protected];[email protected];Full Name <[email protected]>'

(We can also display the contents of these variables using declare -p:)

declare -p IN fields
# declare -- IN="[email protected];[email protected];Full Name <[email protected]>"
# declare -a fields=([0]="[email protected]" [1]="[email protected]" [2]="Full Name <[email protected]>")

Note that read is the quickest way to do the split because there are no forks or external resources called.

Once the array is defined, you can use a simple loop to process each field (or, rather, each element in the array you've now defined):

# `"${fields[@]}"` expands to return every element of `fields` array as a separate argument
for x in "${fields[@]}" ;do
    echo "> [$x]"
    done
# > [[email protected]]
# > [[email protected]]
# > [Full Name <[email protected]>]

Or you could drop each field from the array after processing using a shifting approach, which I like:

while [ "$fields" ] ;do
    echo "> [$fields]"
    # slice the array 
    fields=("${fields[@]:1}")
    done
# > [[email protected]]
# > [[email protected]]
# > [Full Name <[email protected]>]

And if you just want a simple printout of the array, you don't even need to loop over it:

printf "> [%s]\n" "${fields[@]}"
# > [[email protected]]
# > [[email protected]]
# > [Full Name <[email protected]>]

Update: recent >= 4.4

In newer versions of bash, you can also play with the command mapfile:

mapfile -td \; fields < <(printf "%s\0" "$IN")

This syntax preserve special chars, newlines and empty fields!

If you don't want to include empty fields, you could do the following:

mapfile -td \; fields <<<"$IN"
fields[-1]=${fields[-1]%

With mapfile, you can also skip declaring an array and implicitly "loop" over the delimited elements, calling a function on each:

myPubliMail() {
    printf "Seq: %6d: Sending mail to '%s'..." $1 "$2"
    # mail -s "This is not a spam..." "$2" </path/to/body
    printf "\e[3D, done.\n"
}

mapfile < <(printf "%s\0" "$IN") -td \; -c 1 -C myPubliMail

(Note: the \0 at end of the format string is useless if you don't care about empty fields at end of the string or they're not present.)

mapfile < <(echo -n "$IN") -td \; -c 1 -C myPubliMail

# Seq:      0: Sending mail to '[email protected]', done.
# Seq:      1: Sending mail to '[email protected]', done.
# Seq:      2: Sending mail to 'Full Name <[email protected]>', done.

But you could even use newline (mapfile's default) separator:

mapfile <<<"${IN//;/

Or you could use <<<, and in the function body include some processing to drop the newline it adds:

myPubliMail() {
    local seq=$1 dest="${2%

Split string based on delimiter in

If you can't use bash, or if you want to write something that can be used in many different shells, you often can't use bashisms -- and this includes the arrays we've been using in the solutions above.

However, we don't need to use arrays to loop over "elements" of a string. There is a syntax used in many shells for deleting substrings of a string from the first or last occurrence of a pattern. Note that * is a wildcard that stands for zero or more characters:

(The lack of this approach in any solution posted so far is the main reason I'm writing this answer ;)

${var#*SubStr}  # drops substring from start of string up to first occurrence of `SubStr`
${var##*SubStr} # drops substring from start of string up to last occurrence of `SubStr`
${var%SubStr*}  # drops substring from last occurrence of `SubStr` to end of string
${var%%SubStr*} # drops substring from first occurrence of `SubStr` to end of string

As explained by Score_Under:

# and % delete the shortest possible matching substring from the start and end of the string respectively, and

## and %% delete the longest possible matching substring.

Using the above syntax, we can create an approach where we extract substring "elements" from the string by deleting the substrings up to or after the delimiter.

The codeblock below works well in (including Mac OS's bash), , , , , , and 's :

(Thanks to Adam Katz's comment, making this loop a lot simplier!)

IN="[email protected];[email protected];Full Name <[email protected]>"
while [ "$IN" != "$iter" ] ;do
    # extract the substring from start of string up to delimiter.
    iter=${IN%%;*}
    # delete this first "element" AND his separator, from $IN.
    IN="${IN#$iter;}"
    # Print (or doing anything with) the first "element".
    printf '> [%s]\n' "$iter"
done
# > [[email protected]]
# > [[email protected]]
# > [Full Name <[email protected]>]

Why not cut?

cut is useful for extracting columns in big files, but doing forks repetitively (var=$(echo ... | cut ...)) become quickly overkill!

Here is a correct syntax, tested under many using cut, as suggested by This other answer from DougW:

IN="[email protected];[email protected];Full Name <[email protected]>"
i=1
while iter=$(echo "$IN"|cut -d\; -f$i) ; [ -n "$iter" ] ;do
    printf '> [%s]\n' "$iter"
    i=$((i+1))
done

Comparing execution time.

splitByCut() {
    local i=1
    while iter=$(echo "$1"|cut -d\; -f$i) ; [ -n "$iter" ] ;do
        printf '> [%s]\n' "$iter"
        i=$((i+1))
    done
}

splitByMapFile() {
    iterMF() {
        local seq=$1 dest="${2%

Preparing 999 fields:

IN="[email protected];[email protected];Full Name <[email protected]>"
printf -v in40 %333s
in40=${in40// /$IN;}
in40=${in40%;}

Then

start=${EPOCHREALTIME/.};splitByMapFile "$in40" |
    md5sum;elap=00000$((${EPOCHREALTIME/.}-start))
printf 'Elapsed: %.4f secs.\n' ${elap::-6}.${elap: -6}
e35655f2a7fa367144a31f72f55e4dc0  -
Elapsed: 0.0454 secs.

start=${EPOCHREALTIME/.};splitByCut "$in40" |
    md5sum;elap=00000$((${EPOCHREALTIME/.}-start))
printf 'Elapsed: %.4f secs.\n' ${elap::-6}.${elap: -6}
e35655f2a7fa367144a31f72f55e4dc0  -
Elapsed: 2.2212 secs.

Where overall execution time is something like 49x longer, using 1 forks to cut, by field, for less than 1'000 fields!!

\t\n'

We can see that the string IN has been stored into an array named fields, split on the semicolons:


(We can also display the contents of these variables using declare -p:)


Note that read is the quickest way to do the split because there are no forks or external resources called.

Once the array is defined, you can use a simple loop to process each field (or, rather, each element in the array you've now defined):


Or you could drop each field from the array after processing using a shifting approach, which I like:


And if you just want a simple printout of the array, you don't even need to loop over it:


Update: recent >= 4.4

In newer versions of bash, you can also play with the command mapfile:


This syntax preserve special chars, newlines and empty fields!

If you don't want to include empty fields, you could do the following:


With mapfile, you can also skip declaring an array and implicitly "loop" over the delimited elements, calling a function on each:


(Note: the \0 at end of the format string is useless if you don't care about empty fields at end of the string or they're not present.)


But you could even use newline (mapfile's default) separator:


Or you could use <<<, and in the function body include some processing to drop the newline it adds:


Split string based on delimiter in

If you can't use bash, or if you want to write something that can be used in many different shells, you often can't use bashisms -- and this includes the arrays we've been using in the solutions above.

However, we don't need to use arrays to loop over "elements" of a string. There is a syntax used in many shells for deleting substrings of a string from the first or last occurrence of a pattern. Note that * is a wildcard that stands for zero or more characters:

(The lack of this approach in any solution posted so far is the main reason I'm writing this answer ;)


As explained by Score_Under:

# and % delete the shortest possible matching substring from the start and end of the string respectively, and

## and %% delete the longest possible matching substring.

Using the above syntax, we can create an approach where we extract substring "elements" from the string by deleting the substrings up to or after the delimiter.

The codeblock below works well in (including Mac OS's bash), , , , , , and 's :

(Thanks to Adam Katz's comment, making this loop a lot simplier!)


Why not cut?

cut is useful for extracting columns in big files, but doing forks repetitively (var=$(echo ... | cut ...)) become quickly overkill!

Here is a correct syntax, tested under many using cut, as suggested by This other answer from DougW:


Comparing execution time.


Preparing 999 fields:


Then


Where overall execution time is something like 49x longer, using 1 forks to cut, by field, for less than 1'000 fields!!

\n'} # drop '\n' added on last field, by '<<<'

With mapfile, you can also skip declaring an array and implicitly "loop" over the delimited elements, calling a function on each:


(Note: the \0 at end of the format string is useless if you don't care about empty fields at end of the string or they're not present.)


But you could even use newline (mapfile's default) separator:


Or you could use <<<, and in the function body include some processing to drop the newline it adds:


Split string based on delimiter in

If you can't use bash, or if you want to write something that can be used in many different shells, you often can't use bashisms -- and this includes the arrays we've been using in the solutions above.

However, we don't need to use arrays to loop over "elements" of a string. There is a syntax used in many shells for deleting substrings of a string from the first or last occurrence of a pattern. Note that * is a wildcard that stands for zero or more characters:

(The lack of this approach in any solution posted so far is the main reason I'm writing this answer ;)


As explained by Score_Under:

# and % delete the shortest possible matching substring from the start and end of the string respectively, and

## and %% delete the longest possible matching substring.

Using the above syntax, we can create an approach where we extract substring "elements" from the string by deleting the substrings up to or after the delimiter.

The codeblock below works well in (including Mac OS's bash), , , , , , and 's :

(Thanks to Adam Katz's comment, making this loop a lot simplier!)


Why not cut?

cut is useful for extracting columns in big files, but doing forks repetitively (var=$(echo ... | cut ...)) become quickly overkill!

Here is a correct syntax, tested under many using cut, as suggested by This other answer from DougW:


Comparing execution time.


Preparing 999 fields:


Then


Where overall execution time is something like 49x longer, using 1 forks to cut, by field, for less than 1'000 fields!!

\t\n'

We can see that the string IN has been stored into an array named fields, split on the semicolons:


(We can also display the contents of these variables using declare -p:)


Note that read is the quickest way to do the split because there are no forks or external resources called.

Once the array is defined, you can use a simple loop to process each field (or, rather, each element in the array you've now defined):


Or you could drop each field from the array after processing using a shifting approach, which I like:


And if you just want a simple printout of the array, you don't even need to loop over it:


Update: recent >= 4.4

In newer versions of bash, you can also play with the command mapfile:


This syntax preserve special chars, newlines and empty fields!

If you don't want to include empty fields, you could do the following:


With mapfile, you can also skip declaring an array and implicitly "loop" over the delimited elements, calling a function on each:


(Note: the \0 at end of the format string is useless if you don't care about empty fields at end of the string or they're not present.)


But you could even use newline (mapfile's default) separator:


Or you could use <<<, and in the function body include some processing to drop the newline it adds:


Split string based on delimiter in

If you can't use bash, or if you want to write something that can be used in many different shells, you often can't use bashisms -- and this includes the arrays we've been using in the solutions above.

However, we don't need to use arrays to loop over "elements" of a string. There is a syntax used in many shells for deleting substrings of a string from the first or last occurrence of a pattern. Note that * is a wildcard that stands for zero or more characters:

(The lack of this approach in any solution posted so far is the main reason I'm writing this answer ;)


As explained by Score_Under:

# and % delete the shortest possible matching substring from the start and end of the string respectively, and

## and %% delete the longest possible matching substring.

Using the above syntax, we can create an approach where we extract substring "elements" from the string by deleting the substrings up to or after the delimiter.

The codeblock below works well in (including Mac OS's bash), , , , , , and 's :

(Thanks to Adam Katz's comment, making this loop a lot simplier!)


Why not cut?

cut is useful for extracting columns in big files, but doing forks repetitively (var=$(echo ... | cut ...)) become quickly overkill!

Here is a correct syntax, tested under many using cut, as suggested by This other answer from DougW:


Comparing execution time.


Preparing 999 fields:


Then


Where overall execution time is something like 49x longer, using 1 forks to cut, by field, for less than 1'000 fields!!

\n'}" -tc 1 -C myPubliMail # Seq: 0: Sending mail to '[email protected]', done. # Seq: 1: Sending mail to '[email protected]', done. # Seq: 2: Sending mail to 'Full Name <[email protected]>', done.

Or you could use <<<, and in the function body include some processing to drop the newline it adds:


Split string based on delimiter in

If you can't use bash, or if you want to write something that can be used in many different shells, you often can't use bashisms -- and this includes the arrays we've been using in the solutions above.

However, we don't need to use arrays to loop over "elements" of a string. There is a syntax used in many shells for deleting substrings of a string from the first or last occurrence of a pattern. Note that * is a wildcard that stands for zero or more characters:

(The lack of this approach in any solution posted so far is the main reason I'm writing this answer ;)


As explained by Score_Under:

# and % delete the shortest possible matching substring from the start and end of the string respectively, and

## and %% delete the longest possible matching substring.

Using the above syntax, we can create an approach where we extract substring "elements" from the string by deleting the substrings up to or after the delimiter.

The codeblock below works well in (including Mac OS's bash), , , , , , and 's :

(Thanks to Adam Katz's comment, making this loop a lot simplier!)


Why not cut?

cut is useful for extracting columns in big files, but doing forks repetitively (var=$(echo ... | cut ...)) become quickly overkill!

Here is a correct syntax, tested under many using cut, as suggested by This other answer from DougW:


Comparing execution time.


Preparing 999 fields:


Then


Where overall execution time is something like 49x longer, using 1 forks to cut, by field, for less than 1'000 fields!!

\t\n'

We can see that the string IN has been stored into an array named fields, split on the semicolons:


(We can also display the contents of these variables using declare -p:)


Note that read is the quickest way to do the split because there are no forks or external resources called.

Once the array is defined, you can use a simple loop to process each field (or, rather, each element in the array you've now defined):


Or you could drop each field from the array after processing using a shifting approach, which I like:


And if you just want a simple printout of the array, you don't even need to loop over it:


Update: recent >= 4.4

In newer versions of bash, you can also play with the command mapfile:


This syntax preserve special chars, newlines and empty fields!

If you don't want to include empty fields, you could do the following:


With mapfile, you can also skip declaring an array and implicitly "loop" over the delimited elements, calling a function on each:


(Note: the \0 at end of the format string is useless if you don't care about empty fields at end of the string or they're not present.)


But you could even use newline (mapfile's default) separator:


Or you could use <<<, and in the function body include some processing to drop the newline it adds:


Split string based on delimiter in

If you can't use bash, or if you want to write something that can be used in many different shells, you often can't use bashisms -- and this includes the arrays we've been using in the solutions above.

However, we don't need to use arrays to loop over "elements" of a string. There is a syntax used in many shells for deleting substrings of a string from the first or last occurrence of a pattern. Note that * is a wildcard that stands for zero or more characters:

(The lack of this approach in any solution posted so far is the main reason I'm writing this answer ;)


As explained by Score_Under:

# and % delete the shortest possible matching substring from the start and end of the string respectively, and

## and %% delete the longest possible matching substring.

Using the above syntax, we can create an approach where we extract substring "elements" from the string by deleting the substrings up to or after the delimiter.

The codeblock below works well in (including Mac OS's bash), , , , , , and 's :

(Thanks to Adam Katz's comment, making this loop a lot simplier!)


Why not cut?

cut is useful for extracting columns in big files, but doing forks repetitively (var=$(echo ... | cut ...)) become quickly overkill!

Here is a correct syntax, tested under many using cut, as suggested by This other answer from DougW:


Comparing execution time.


Preparing 999 fields:


Then


Where overall execution time is something like 49x longer, using 1 forks to cut, by field, for less than 1'000 fields!!

\n'} # drop '\n' added on last field, by '<<<'

With mapfile, you can also skip declaring an array and implicitly "loop" over the delimited elements, calling a function on each:


(Note: the \0 at end of the format string is useless if you don't care about empty fields at end of the string or they're not present.)


But you could even use newline (mapfile's default) separator:


Or you could use <<<, and in the function body include some processing to drop the newline it adds:


Split string based on delimiter in

If you can't use bash, or if you want to write something that can be used in many different shells, you often can't use bashisms -- and this includes the arrays we've been using in the solutions above.

However, we don't need to use arrays to loop over "elements" of a string. There is a syntax used in many shells for deleting substrings of a string from the first or last occurrence of a pattern. Note that * is a wildcard that stands for zero or more characters:

(The lack of this approach in any solution posted so far is the main reason I'm writing this answer ;)


As explained by Score_Under:

# and % delete the shortest possible matching substring from the start and end of the string respectively, and

## and %% delete the longest possible matching substring.

Using the above syntax, we can create an approach where we extract substring "elements" from the string by deleting the substrings up to or after the delimiter.

The codeblock below works well in (including Mac OS's bash), , , , , , and 's :

(Thanks to Adam Katz's comment, making this loop a lot simplier!)


Why not cut?

cut is useful for extracting columns in big files, but doing forks repetitively (var=$(echo ... | cut ...)) become quickly overkill!

Here is a correct syntax, tested under many using cut, as suggested by This other answer from DougW:


Comparing execution time.


Preparing 999 fields:


Then


Where overall execution time is something like 49x longer, using 1 forks to cut, by field, for less than 1'000 fields!!

\t\n'

We can see that the string IN has been stored into an array named fields, split on the semicolons:


(We can also display the contents of these variables using declare -p:)


Note that read is the quickest way to do the split because there are no forks or external resources called.

Once the array is defined, you can use a simple loop to process each field (or, rather, each element in the array you've now defined):


Or you could drop each field from the array after processing using a shifting approach, which I like:


And if you just want a simple printout of the array, you don't even need to loop over it:


Update: recent >= 4.4

In newer versions of bash, you can also play with the command mapfile:


This syntax preserve special chars, newlines and empty fields!

If you don't want to include empty fields, you could do the following:


With mapfile, you can also skip declaring an array and implicitly "loop" over the delimited elements, calling a function on each:


(Note: the \0 at end of the format string is useless if you don't care about empty fields at end of the string or they're not present.)


But you could even use newline (mapfile's default) separator:


Or you could use <<<, and in the function body include some processing to drop the newline it adds:


Split string based on delimiter in

If you can't use bash, or if you want to write something that can be used in many different shells, you often can't use bashisms -- and this includes the arrays we've been using in the solutions above.

However, we don't need to use arrays to loop over "elements" of a string. There is a syntax used in many shells for deleting substrings of a string from the first or last occurrence of a pattern. Note that * is a wildcard that stands for zero or more characters:

(The lack of this approach in any solution posted so far is the main reason I'm writing this answer ;)


As explained by Score_Under:

# and % delete the shortest possible matching substring from the start and end of the string respectively, and

## and %% delete the longest possible matching substring.

Using the above syntax, we can create an approach where we extract substring "elements" from the string by deleting the substrings up to or after the delimiter.

The codeblock below works well in (including Mac OS's bash), , , , , , and 's :

(Thanks to Adam Katz's comment, making this loop a lot simplier!)


Why not cut?

cut is useful for extracting columns in big files, but doing forks repetitively (var=$(echo ... | cut ...)) become quickly overkill!

Here is a correct syntax, tested under many using cut, as suggested by This other answer from DougW:


Comparing execution time.


Preparing 999 fields:


Then


Where overall execution time is something like 49x longer, using 1 forks to cut, by field, for less than 1'000 fields!!

\n'}" printf "Seq: %6d: Sending mail to '%s'..." $seq "$dest" # mail -s "This is not a spam..." "$dest" </path/to/body printf "\e[3D, done.\n" } mapfile <<<"$IN" -td \; -c 1 -C myPubliMail # Renders the same output: # Seq: 0: Sending mail to '[email protected]', done. # Seq: 1: Sending mail to '[email protected]', done. # Seq: 2: Sending mail to 'Full Name <[email protected]>', done.

Split string based on delimiter in

If you can't use bash, or if you want to write something that can be used in many different shells, you often can't use bashisms -- and this includes the arrays we've been using in the solutions above.

However, we don't need to use arrays to loop over "elements" of a string. There is a syntax used in many shells for deleting substrings of a string from the first or last occurrence of a pattern. Note that * is a wildcard that stands for zero or more characters:

(The lack of this approach in any solution posted so far is the main reason I'm writing this answer ;)


As explained by Score_Under:

# and % delete the shortest possible matching substring from the start and end of the string respectively, and

## and %% delete the longest possible matching substring.

Using the above syntax, we can create an approach where we extract substring "elements" from the string by deleting the substrings up to or after the delimiter.

The codeblock below works well in (including Mac OS's bash), , , , , , and 's :

(Thanks to Adam Katz's comment, making this loop a lot simplier!)


Why not cut?

cut is useful for extracting columns in big files, but doing forks repetitively (var=$(echo ... | cut ...)) become quickly overkill!

Here is a correct syntax, tested under many using cut, as suggested by This other answer from DougW:


Comparing execution time.


Preparing 999 fields:


Then


Where overall execution time is something like 49x longer, using 1 forks to cut, by field, for less than 1'000 fields!!

\t\n'

We can see that the string IN has been stored into an array named fields, split on the semicolons:


(We can also display the contents of these variables using declare -p:)


Note that read is the quickest way to do the split because there are no forks or external resources called.

Once the array is defined, you can use a simple loop to process each field (or, rather, each element in the array you've now defined):


Or you could drop each field from the array after processing using a shifting approach, which I like:


And if you just want a simple printout of the array, you don't even need to loop over it:


Update: recent >= 4.4

In newer versions of bash, you can also play with the command mapfile:


This syntax preserve special chars, newlines and empty fields!

If you don't want to include empty fields, you could do the following:


With mapfile, you can also skip declaring an array and implicitly "loop" over the delimited elements, calling a function on each:


(Note: the \0 at end of the format string is useless if you don't care about empty fields at end of the string or they're not present.)


But you could even use newline (mapfile's default) separator:


Or you could use <<<, and in the function body include some processing to drop the newline it adds:


Split string based on delimiter in

If you can't use bash, or if you want to write something that can be used in many different shells, you often can't use bashisms -- and this includes the arrays we've been using in the solutions above.

However, we don't need to use arrays to loop over "elements" of a string. There is a syntax used in many shells for deleting substrings of a string from the first or last occurrence of a pattern. Note that * is a wildcard that stands for zero or more characters:

(The lack of this approach in any solution posted so far is the main reason I'm writing this answer ;)


As explained by Score_Under:

# and % delete the shortest possible matching substring from the start and end of the string respectively, and

## and %% delete the longest possible matching substring.

Using the above syntax, we can create an approach where we extract substring "elements" from the string by deleting the substrings up to or after the delimiter.

The codeblock below works well in (including Mac OS's bash), , , , , , and 's :

(Thanks to Adam Katz's comment, making this loop a lot simplier!)


Why not cut?

cut is useful for extracting columns in big files, but doing forks repetitively (var=$(echo ... | cut ...)) become quickly overkill!

Here is a correct syntax, tested under many using cut, as suggested by This other answer from DougW:


Comparing execution time.


Preparing 999 fields:


Then


Where overall execution time is something like 49x longer, using 1 forks to cut, by field, for less than 1'000 fields!!

\n'} # drop '\n' added on last field, by '<<<'

With mapfile, you can also skip declaring an array and implicitly "loop" over the delimited elements, calling a function on each:


(Note: the \0 at end of the format string is useless if you don't care about empty fields at end of the string or they're not present.)


But you could even use newline (mapfile's default) separator:


Or you could use <<<, and in the function body include some processing to drop the newline it adds:


Split string based on delimiter in

If you can't use bash, or if you want to write something that can be used in many different shells, you often can't use bashisms -- and this includes the arrays we've been using in the solutions above.

However, we don't need to use arrays to loop over "elements" of a string. There is a syntax used in many shells for deleting substrings of a string from the first or last occurrence of a pattern. Note that * is a wildcard that stands for zero or more characters:

(The lack of this approach in any solution posted so far is the main reason I'm writing this answer ;)


As explained by Score_Under:

# and % delete the shortest possible matching substring from the start and end of the string respectively, and

## and %% delete the longest possible matching substring.

Using the above syntax, we can create an approach where we extract substring "elements" from the string by deleting the substrings up to or after the delimiter.

The codeblock below works well in (including Mac OS's bash), , , , , , and 's :

(Thanks to Adam Katz's comment, making this loop a lot simplier!)


Why not cut?

cut is useful for extracting columns in big files, but doing forks repetitively (var=$(echo ... | cut ...)) become quickly overkill!

Here is a correct syntax, tested under many using cut, as suggested by This other answer from DougW:


Comparing execution time.


Preparing 999 fields:


Then


Where overall execution time is something like 49x longer, using 1 forks to cut, by field, for less than 1'000 fields!!

\t\n'

We can see that the string IN has been stored into an array named fields, split on the semicolons:


(We can also display the contents of these variables using declare -p:)


Note that read is the quickest way to do the split because there are no forks or external resources called.

Once the array is defined, you can use a simple loop to process each field (or, rather, each element in the array you've now defined):


Or you could drop each field from the array after processing using a shifting approach, which I like:


And if you just want a simple printout of the array, you don't even need to loop over it:


Update: recent >= 4.4

In newer versions of bash, you can also play with the command mapfile:


This syntax preserve special chars, newlines and empty fields!

If you don't want to include empty fields, you could do the following:


With mapfile, you can also skip declaring an array and implicitly "loop" over the delimited elements, calling a function on each:


(Note: the \0 at end of the format string is useless if you don't care about empty fields at end of the string or they're not present.)


But you could even use newline (mapfile's default) separator:


Or you could use <<<, and in the function body include some processing to drop the newline it adds:


Split string based on delimiter in

If you can't use bash, or if you want to write something that can be used in many different shells, you often can't use bashisms -- and this includes the arrays we've been using in the solutions above.

However, we don't need to use arrays to loop over "elements" of a string. There is a syntax used in many shells for deleting substrings of a string from the first or last occurrence of a pattern. Note that * is a wildcard that stands for zero or more characters:

(The lack of this approach in any solution posted so far is the main reason I'm writing this answer ;)


As explained by Score_Under:

# and % delete the shortest possible matching substring from the start and end of the string respectively, and

## and %% delete the longest possible matching substring.

Using the above syntax, we can create an approach where we extract substring "elements" from the string by deleting the substrings up to or after the delimiter.

The codeblock below works well in (including Mac OS's bash), , , , , , and 's :

(Thanks to Adam Katz's comment, making this loop a lot simplier!)


Why not cut?

cut is useful for extracting columns in big files, but doing forks repetitively (var=$(echo ... | cut ...)) become quickly overkill!

Here is a correct syntax, tested under many using cut, as suggested by This other answer from DougW:


Comparing execution time.


Preparing 999 fields:


Then


Where overall execution time is something like 49x longer, using 1 forks to cut, by field, for less than 1'000 fields!!

\n'}" -tc 1 -C myPubliMail # Seq: 0: Sending mail to '[email protected]', done. # Seq: 1: Sending mail to '[email protected]', done. # Seq: 2: Sending mail to 'Full Name <[email protected]>', done.

Or you could use <<<, and in the function body include some processing to drop the newline it adds:


Split string based on delimiter in

If you can't use bash, or if you want to write something that can be used in many different shells, you often can't use bashisms -- and this includes the arrays we've been using in the solutions above.

However, we don't need to use arrays to loop over "elements" of a string. There is a syntax used in many shells for deleting substrings of a string from the first or last occurrence of a pattern. Note that * is a wildcard that stands for zero or more characters:

(The lack of this approach in any solution posted so far is the main reason I'm writing this answer ;)


As explained by Score_Under:

# and % delete the shortest possible matching substring from the start and end of the string respectively, and

## and %% delete the longest possible matching substring.

Using the above syntax, we can create an approach where we extract substring "elements" from the string by deleting the substrings up to or after the delimiter.

The codeblock below works well in (including Mac OS's bash), , , , , , and 's :

(Thanks to Adam Katz's comment, making this loop a lot simplier!)


Why not cut?

cut is useful for extracting columns in big files, but doing forks repetitively (var=$(echo ... | cut ...)) become quickly overkill!

Here is a correct syntax, tested under many using cut, as suggested by This other answer from DougW:


Comparing execution time.


Preparing 999 fields:


Then


Where overall execution time is something like 49x longer, using 1 forks to cut, by field, for less than 1'000 fields!!

\t\n'

We can see that the string IN has been stored into an array named fields, split on the semicolons:


(We can also display the contents of these variables using declare -p:)


Note that read is the quickest way to do the split because there are no forks or external resources called.

Once the array is defined, you can use a simple loop to process each field (or, rather, each element in the array you've now defined):


Or you could drop each field from the array after processing using a shifting approach, which I like:


And if you just want a simple printout of the array, you don't even need to loop over it:


Update: recent >= 4.4

In newer versions of bash, you can also play with the command mapfile:


This syntax preserve special chars, newlines and empty fields!

If you don't want to include empty fields, you could do the following:


With mapfile, you can also skip declaring an array and implicitly "loop" over the delimited elements, calling a function on each:


(Note: the \0 at end of the format string is useless if you don't care about empty fields at end of the string or they're not present.)


But you could even use newline (mapfile's default) separator:


Or you could use <<<, and in the function body include some processing to drop the newline it adds:


Split string based on delimiter in

If you can't use bash, or if you want to write something that can be used in many different shells, you often can't use bashisms -- and this includes the arrays we've been using in the solutions above.

However, we don't need to use arrays to loop over "elements" of a string. There is a syntax used in many shells for deleting substrings of a string from the first or last occurrence of a pattern. Note that * is a wildcard that stands for zero or more characters:

(The lack of this approach in any solution posted so far is the main reason I'm writing this answer ;)


As explained by Score_Under:

# and % delete the shortest possible matching substring from the start and end of the string respectively, and

## and %% delete the longest possible matching substring.

Using the above syntax, we can create an approach where we extract substring "elements" from the string by deleting the substrings up to or after the delimiter.

The codeblock below works well in (including Mac OS's bash), , , , , , and 's :

(Thanks to Adam Katz's comment, making this loop a lot simplier!)


Why not cut?

cut is useful for extracting columns in big files, but doing forks repetitively (var=$(echo ... | cut ...)) become quickly overkill!

Here is a correct syntax, tested under many using cut, as suggested by This other answer from DougW:


Comparing execution time.


Preparing 999 fields:


Then


Where overall execution time is something like 49x longer, using 1 forks to cut, by field, for less than 1'000 fields!!

\n'} # drop '\n' added on last field, by '<<<'

With mapfile, you can also skip declaring an array and implicitly "loop" over the delimited elements, calling a function on each:


(Note: the \0 at end of the format string is useless if you don't care about empty fields at end of the string or they're not present.)


But you could even use newline (mapfile's default) separator:


Or you could use <<<, and in the function body include some processing to drop the newline it adds:


Split string based on delimiter in

If you can't use bash, or if you want to write something that can be used in many different shells, you often can't use bashisms -- and this includes the arrays we've been using in the solutions above.

However, we don't need to use arrays to loop over "elements" of a string. There is a syntax used in many shells for deleting substrings of a string from the first or last occurrence of a pattern. Note that * is a wildcard that stands for zero or more characters:

(The lack of this approach in any solution posted so far is the main reason I'm writing this answer ;)


As explained by Score_Under:

# and % delete the shortest possible matching substring from the start and end of the string respectively, and

## and %% delete the longest possible matching substring.

Using the above syntax, we can create an approach where we extract substring "elements" from the string by deleting the substrings up to or after the delimiter.

The codeblock below works well in (including Mac OS's bash), , , , , , and 's :

(Thanks to Adam Katz's comment, making this loop a lot simplier!)


Why not cut?

cut is useful for extracting columns in big files, but doing forks repetitively (var=$(echo ... | cut ...)) become quickly overkill!

Here is a correct syntax, tested under many using cut, as suggested by This other answer from DougW:


Comparing execution time.


Preparing 999 fields:


Then


Where overall execution time is something like 49x longer, using 1 forks to cut, by field, for less than 1'000 fields!!

\t\n'

We can see that the string IN has been stored into an array named fields, split on the semicolons:


(We can also display the contents of these variables using declare -p:)


Note that read is the quickest way to do the split because there are no forks or external resources called.

Once the array is defined, you can use a simple loop to process each field (or, rather, each element in the array you've now defined):


Or you could drop each field from the array after processing using a shifting approach, which I like:


And if you just want a simple printout of the array, you don't even need to loop over it:


Update: recent >= 4.4

In newer versions of bash, you can also play with the command mapfile:


This syntax preserve special chars, newlines and empty fields!

If you don't want to include empty fields, you could do the following:


With mapfile, you can also skip declaring an array and implicitly "loop" over the delimited elements, calling a function on each:


(Note: the \0 at end of the format string is useless if you don't care about empty fields at end of the string or they're not present.)


But you could even use newline (mapfile's default) separator:


Or you could use <<<, and in the function body include some processing to drop the newline it adds:


Split string based on delimiter in

If you can't use bash, or if you want to write something that can be used in many different shells, you often can't use bashisms -- and this includes the arrays we've been using in the solutions above.

However, we don't need to use arrays to loop over "elements" of a string. There is a syntax used in many shells for deleting substrings of a string from the first or last occurrence of a pattern. Note that * is a wildcard that stands for zero or more characters:

(The lack of this approach in any solution posted so far is the main reason I'm writing this answer ;)


As explained by Score_Under:

# and % delete the shortest possible matching substring from the start and end of the string respectively, and

## and %% delete the longest possible matching substring.

Using the above syntax, we can create an approach where we extract substring "elements" from the string by deleting the substrings up to or after the delimiter.

The codeblock below works well in (including Mac OS's bash), , , , , , and 's :

(Thanks to Adam Katz's comment, making this loop a lot simplier!)


Why not cut?

cut is useful for extracting columns in big files, but doing forks repetitively (var=$(echo ... | cut ...)) become quickly overkill!

Here is a correct syntax, tested under many using cut, as suggested by This other answer from DougW:


Comparing execution time.


Preparing 999 fields:


Then


Where overall execution time is something like 49x longer, using 1 forks to cut, by field, for less than 1'000 fields!!

\n'}" [[ $2 ]] && printf "> [%s]\n" "$dest" } mapfile <<<"${1//;/

Preparing 999 fields:


Then


Where overall execution time is something like 49x longer, using 1 forks to cut, by field, for less than 1'000 fields!!

\t\n'

We can see that the string IN has been stored into an array named fields, split on the semicolons:


(We can also display the contents of these variables using declare -p:)


Note that read is the quickest way to do the split because there are no forks or external resources called.

Once the array is defined, you can use a simple loop to process each field (or, rather, each element in the array you've now defined):


Or you could drop each field from the array after processing using a shifting approach, which I like:


And if you just want a simple printout of the array, you don't even need to loop over it:


Update: recent >= 4.4

In newer versions of bash, you can also play with the command mapfile:


This syntax preserve special chars, newlines and empty fields!

If you don't want to include empty fields, you could do the following:


With mapfile, you can also skip declaring an array and implicitly "loop" over the delimited elements, calling a function on each:


(Note: the \0 at end of the format string is useless if you don't care about empty fields at end of the string or they're not present.)


But you could even use newline (mapfile's default) separator:


Or you could use <<<, and in the function body include some processing to drop the newline it adds:


Split string based on delimiter in

If you can't use bash, or if you want to write something that can be used in many different shells, you often can't use bashisms -- and this includes the arrays we've been using in the solutions above.

However, we don't need to use arrays to loop over "elements" of a string. There is a syntax used in many shells for deleting substrings of a string from the first or last occurrence of a pattern. Note that * is a wildcard that stands for zero or more characters:

(The lack of this approach in any solution posted so far is the main reason I'm writing this answer ;)


As explained by Score_Under:

# and % delete the shortest possible matching substring from the start and end of the string respectively, and

## and %% delete the longest possible matching substring.

Using the above syntax, we can create an approach where we extract substring "elements" from the string by deleting the substrings up to or after the delimiter.

The codeblock below works well in (including Mac OS's bash), , , , , , and 's :

(Thanks to Adam Katz's comment, making this loop a lot simplier!)


Why not cut?

cut is useful for extracting columns in big files, but doing forks repetitively (var=$(echo ... | cut ...)) become quickly overkill!

Here is a correct syntax, tested under many using cut, as suggested by This other answer from DougW:


Comparing execution time.


Preparing 999 fields:


Then


Where overall execution time is something like 49x longer, using 1 forks to cut, by field, for less than 1'000 fields!!

\n'} # drop '\n' added on last field, by '<<<'

With mapfile, you can also skip declaring an array and implicitly "loop" over the delimited elements, calling a function on each:


(Note: the \0 at end of the format string is useless if you don't care about empty fields at end of the string or they're not present.)


But you could even use newline (mapfile's default) separator:


Or you could use <<<, and in the function body include some processing to drop the newline it adds:


Split string based on delimiter in

If you can't use bash, or if you want to write something that can be used in many different shells, you often can't use bashisms -- and this includes the arrays we've been using in the solutions above.

However, we don't need to use arrays to loop over "elements" of a string. There is a syntax used in many shells for deleting substrings of a string from the first or last occurrence of a pattern. Note that * is a wildcard that stands for zero or more characters:

(The lack of this approach in any solution posted so far is the main reason I'm writing this answer ;)


As explained by Score_Under:

# and % delete the shortest possible matching substring from the start and end of the string respectively, and

## and %% delete the longest possible matching substring.

Using the above syntax, we can create an approach where we extract substring "elements" from the string by deleting the substrings up to or after the delimiter.

The codeblock below works well in (including Mac OS's bash), , , , , , and 's :

(Thanks to Adam Katz's comment, making this loop a lot simplier!)


Why not cut?

cut is useful for extracting columns in big files, but doing forks repetitively (var=$(echo ... | cut ...)) become quickly overkill!

Here is a correct syntax, tested under many using cut, as suggested by This other answer from DougW:


Comparing execution time.


Preparing 999 fields:


Then


Where overall execution time is something like 49x longer, using 1 forks to cut, by field, for less than 1'000 fields!!

\t\n'

We can see that the string IN has been stored into an array named fields, split on the semicolons:


(We can also display the contents of these variables using declare -p:)


Note that read is the quickest way to do the split because there are no forks or external resources called.

Once the array is defined, you can use a simple loop to process each field (or, rather, each element in the array you've now defined):


Or you could drop each field from the array after processing using a shifting approach, which I like:


And if you just want a simple printout of the array, you don't even need to loop over it:


Update: recent >= 4.4

In newer versions of bash, you can also play with the command mapfile:


This syntax preserve special chars, newlines and empty fields!

If you don't want to include empty fields, you could do the following:


With mapfile, you can also skip declaring an array and implicitly "loop" over the delimited elements, calling a function on each:


(Note: the \0 at end of the format string is useless if you don't care about empty fields at end of the string or they're not present.)


But you could even use newline (mapfile's default) separator:


Or you could use <<<, and in the function body include some processing to drop the newline it adds:


Split string based on delimiter in

If you can't use bash, or if you want to write something that can be used in many different shells, you often can't use bashisms -- and this includes the arrays we've been using in the solutions above.

However, we don't need to use arrays to loop over "elements" of a string. There is a syntax used in many shells for deleting substrings of a string from the first or last occurrence of a pattern. Note that * is a wildcard that stands for zero or more characters:

(The lack of this approach in any solution posted so far is the main reason I'm writing this answer ;)


As explained by Score_Under:

# and % delete the shortest possible matching substring from the start and end of the string respectively, and

## and %% delete the longest possible matching substring.

Using the above syntax, we can create an approach where we extract substring "elements" from the string by deleting the substrings up to or after the delimiter.

The codeblock below works well in (including Mac OS's bash), , , , , , and 's :

(Thanks to Adam Katz's comment, making this loop a lot simplier!)


Why not cut?

cut is useful for extracting columns in big files, but doing forks repetitively (var=$(echo ... | cut ...)) become quickly overkill!

Here is a correct syntax, tested under many using cut, as suggested by This other answer from DougW:


Comparing execution time.


Preparing 999 fields:


Then


Where overall execution time is something like 49x longer, using 1 forks to cut, by field, for less than 1'000 fields!!

\n'}" -tc 1 -C myPubliMail # Seq: 0: Sending mail to '[email protected]', done. # Seq: 1: Sending mail to '[email protected]', done. # Seq: 2: Sending mail to 'Full Name <[email protected]>', done.

Or you could use <<<, and in the function body include some processing to drop the newline it adds:


Split string based on delimiter in

If you can't use bash, or if you want to write something that can be used in many different shells, you often can't use bashisms -- and this includes the arrays we've been using in the solutions above.

However, we don't need to use arrays to loop over "elements" of a string. There is a syntax used in many shells for deleting substrings of a string from the first or last occurrence of a pattern. Note that * is a wildcard that stands for zero or more characters:

(The lack of this approach in any solution posted so far is the main reason I'm writing this answer ;)


As explained by Score_Under:

# and % delete the shortest possible matching substring from the start and end of the string respectively, and

## and %% delete the longest possible matching substring.

Using the above syntax, we can create an approach where we extract substring "elements" from the string by deleting the substrings up to or after the delimiter.

The codeblock below works well in (including Mac OS's bash), , , , , , and 's :

(Thanks to Adam Katz's comment, making this loop a lot simplier!)


Why not cut?

cut is useful for extracting columns in big files, but doing forks repetitively (var=$(echo ... | cut ...)) become quickly overkill!

Here is a correct syntax, tested under many using cut, as suggested by This other answer from DougW:


Comparing execution time.


Preparing 999 fields:


Then


Where overall execution time is something like 49x longer, using 1 forks to cut, by field, for less than 1'000 fields!!

\t\n'

We can see that the string IN has been stored into an array named fields, split on the semicolons:


(We can also display the contents of these variables using declare -p:)


Note that read is the quickest way to do the split because there are no forks or external resources called.

Once the array is defined, you can use a simple loop to process each field (or, rather, each element in the array you've now defined):


Or you could drop each field from the array after processing using a shifting approach, which I like:


And if you just want a simple printout of the array, you don't even need to loop over it:


Update: recent >= 4.4

In newer versions of bash, you can also play with the command mapfile:


This syntax preserve special chars, newlines and empty fields!

If you don't want to include empty fields, you could do the following:


With mapfile, you can also skip declaring an array and implicitly "loop" over the delimited elements, calling a function on each:


(Note: the \0 at end of the format string is useless if you don't care about empty fields at end of the string or they're not present.)


But you could even use newline (mapfile's default) separator:


Or you could use <<<, and in the function body include some processing to drop the newline it adds:


Split string based on delimiter in

If you can't use bash, or if you want to write something that can be used in many different shells, you often can't use bashisms -- and this includes the arrays we've been using in the solutions above.

However, we don't need to use arrays to loop over "elements" of a string. There is a syntax used in many shells for deleting substrings of a string from the first or last occurrence of a pattern. Note that * is a wildcard that stands for zero or more characters:

(The lack of this approach in any solution posted so far is the main reason I'm writing this answer ;)


As explained by Score_Under:

# and % delete the shortest possible matching substring from the start and end of the string respectively, and

## and %% delete the longest possible matching substring.

Using the above syntax, we can create an approach where we extract substring "elements" from the string by deleting the substrings up to or after the delimiter.

The codeblock below works well in (including Mac OS's bash), , , , , , and 's :

(Thanks to Adam Katz's comment, making this loop a lot simplier!)


Why not cut?

cut is useful for extracting columns in big files, but doing forks repetitively (var=$(echo ... | cut ...)) become quickly overkill!

Here is a correct syntax, tested under many using cut, as suggested by This other answer from DougW:


Comparing execution time.


Preparing 999 fields:


Then


Where overall execution time is something like 49x longer, using 1 forks to cut, by field, for less than 1'000 fields!!

\n'} # drop '\n' added on last field, by '<<<'

With mapfile, you can also skip declaring an array and implicitly "loop" over the delimited elements, calling a function on each:


(Note: the \0 at end of the format string is useless if you don't care about empty fields at end of the string or they're not present.)


But you could even use newline (mapfile's default) separator:


Or you could use <<<, and in the function body include some processing to drop the newline it adds:


Split string based on delimiter in

If you can't use bash, or if you want to write something that can be used in many different shells, you often can't use bashisms -- and this includes the arrays we've been using in the solutions above.

However, we don't need to use arrays to loop over "elements" of a string. There is a syntax used in many shells for deleting substrings of a string from the first or last occurrence of a pattern. Note that * is a wildcard that stands for zero or more characters:

(The lack of this approach in any solution posted so far is the main reason I'm writing this answer ;)


As explained by Score_Under:

# and % delete the shortest possible matching substring from the start and end of the string respectively, and

## and %% delete the longest possible matching substring.

Using the above syntax, we can create an approach where we extract substring "elements" from the string by deleting the substrings up to or after the delimiter.

The codeblock below works well in (including Mac OS's bash), , , , , , and 's :

(Thanks to Adam Katz's comment, making this loop a lot simplier!)


Why not cut?

cut is useful for extracting columns in big files, but doing forks repetitively (var=$(echo ... | cut ...)) become quickly overkill!

Here is a correct syntax, tested under many using cut, as suggested by This other answer from DougW:


Comparing execution time.


Preparing 999 fields:


Then


Where overall execution time is something like 49x longer, using 1 forks to cut, by field, for less than 1'000 fields!!

\t\n'

We can see that the string IN has been stored into an array named fields, split on the semicolons:


(We can also display the contents of these variables using declare -p:)


Note that read is the quickest way to do the split because there are no forks or external resources called.

Once the array is defined, you can use a simple loop to process each field (or, rather, each element in the array you've now defined):


Or you could drop each field from the array after processing using a shifting approach, which I like:


And if you just want a simple printout of the array, you don't even need to loop over it:


Update: recent >= 4.4

In newer versions of bash, you can also play with the command mapfile:


This syntax preserve special chars, newlines and empty fields!

If you don't want to include empty fields, you could do the following:


With mapfile, you can also skip declaring an array and implicitly "loop" over the delimited elements, calling a function on each:


(Note: the \0 at end of the format string is useless if you don't care about empty fields at end of the string or they're not present.)


But you could even use newline (mapfile's default) separator:


Or you could use <<<, and in the function body include some processing to drop the newline it adds:


Split string based on delimiter in

If you can't use bash, or if you want to write something that can be used in many different shells, you often can't use bashisms -- and this includes the arrays we've been using in the solutions above.

However, we don't need to use arrays to loop over "elements" of a string. There is a syntax used in many shells for deleting substrings of a string from the first or last occurrence of a pattern. Note that * is a wildcard that stands for zero or more characters:

(The lack of this approach in any solution posted so far is the main reason I'm writing this answer ;)


As explained by Score_Under:

# and % delete the shortest possible matching substring from the start and end of the string respectively, and

## and %% delete the longest possible matching substring.

Using the above syntax, we can create an approach where we extract substring "elements" from the string by deleting the substrings up to or after the delimiter.

The codeblock below works well in (including Mac OS's bash), , , , , , and 's :

(Thanks to Adam Katz's comment, making this loop a lot simplier!)


Why not cut?

cut is useful for extracting columns in big files, but doing forks repetitively (var=$(echo ... | cut ...)) become quickly overkill!

Here is a correct syntax, tested under many using cut, as suggested by This other answer from DougW:


Comparing execution time.


Preparing 999 fields:


Then


Where overall execution time is something like 49x longer, using 1 forks to cut, by field, for less than 1'000 fields!!

\n'}" printf "Seq: %6d: Sending mail to '%s'..." $seq "$dest" # mail -s "This is not a spam..." "$dest" </path/to/body printf "\e[3D, done.\n" } mapfile <<<"$IN" -td \; -c 1 -C myPubliMail # Renders the same output: # Seq: 0: Sending mail to '[email protected]', done. # Seq: 1: Sending mail to '[email protected]', done. # Seq: 2: Sending mail to 'Full Name <[email protected]>', done.

Split string based on delimiter in

If you can't use bash, or if you want to write something that can be used in many different shells, you often can't use bashisms -- and this includes the arrays we've been using in the solutions above.

However, we don't need to use arrays to loop over "elements" of a string. There is a syntax used in many shells for deleting substrings of a string from the first or last occurrence of a pattern. Note that * is a wildcard that stands for zero or more characters:

(The lack of this approach in any solution posted so far is the main reason I'm writing this answer ;)


As explained by Score_Under:

# and % delete the shortest possible matching substring from the start and end of the string respectively, and

## and %% delete the longest possible matching substring.

Using the above syntax, we can create an approach where we extract substring "elements" from the string by deleting the substrings up to or after the delimiter.

The codeblock below works well in (including Mac OS's bash), , , , , , and 's :

(Thanks to Adam Katz's comment, making this loop a lot simplier!)


Why not cut?

cut is useful for extracting columns in big files, but doing forks repetitively (var=$(echo ... | cut ...)) become quickly overkill!

Here is a correct syntax, tested under many using cut, as suggested by This other answer from DougW:


Comparing execution time.


Preparing 999 fields:


Then


Where overall execution time is something like 49x longer, using 1 forks to cut, by field, for less than 1'000 fields!!

\t\n'

We can see that the string IN has been stored into an array named fields, split on the semicolons:


(We can also display the contents of these variables using declare -p:)


Note that read is the quickest way to do the split because there are no forks or external resources called.

Once the array is defined, you can use a simple loop to process each field (or, rather, each element in the array you've now defined):


Or you could drop each field from the array after processing using a shifting approach, which I like:


And if you just want a simple printout of the array, you don't even need to loop over it:


Update: recent >= 4.4

In newer versions of bash, you can also play with the command mapfile:


This syntax preserve special chars, newlines and empty fields!

If you don't want to include empty fields, you could do the following:


With mapfile, you can also skip declaring an array and implicitly "loop" over the delimited elements, calling a function on each:


(Note: the \0 at end of the format string is useless if you don't care about empty fields at end of the string or they're not present.)


But you could even use newline (mapfile's default) separator:


Or you could use <<<, and in the function body include some processing to drop the newline it adds:


Split string based on delimiter in

If you can't use bash, or if you want to write something that can be used in many different shells, you often can't use bashisms -- and this includes the arrays we've been using in the solutions above.

However, we don't need to use arrays to loop over "elements" of a string. There is a syntax used in many shells for deleting substrings of a string from the first or last occurrence of a pattern. Note that * is a wildcard that stands for zero or more characters:

(The lack of this approach in any solution posted so far is the main reason I'm writing this answer ;)


As explained by Score_Under:

# and % delete the shortest possible matching substring from the start and end of the string respectively, and

## and %% delete the longest possible matching substring.

Using the above syntax, we can create an approach where we extract substring "elements" from the string by deleting the substrings up to or after the delimiter.

The codeblock below works well in (including Mac OS's bash), , , , , , and 's :

(Thanks to Adam Katz's comment, making this loop a lot simplier!)


Why not cut?

cut is useful for extracting columns in big files, but doing forks repetitively (var=$(echo ... | cut ...)) become quickly overkill!

Here is a correct syntax, tested under many using cut, as suggested by This other answer from DougW:


Comparing execution time.


Preparing 999 fields:


Then


Where overall execution time is something like 49x longer, using 1 forks to cut, by field, for less than 1'000 fields!!

\n'} # drop '\n' added on last field, by '<<<'

With mapfile, you can also skip declaring an array and implicitly "loop" over the delimited elements, calling a function on each:


(Note: the \0 at end of the format string is useless if you don't care about empty fields at end of the string or they're not present.)


But you could even use newline (mapfile's default) separator:


Or you could use <<<, and in the function body include some processing to drop the newline it adds:


Split string based on delimiter in

If you can't use bash, or if you want to write something that can be used in many different shells, you often can't use bashisms -- and this includes the arrays we've been using in the solutions above.

However, we don't need to use arrays to loop over "elements" of a string. There is a syntax used in many shells for deleting substrings of a string from the first or last occurrence of a pattern. Note that * is a wildcard that stands for zero or more characters:

(The lack of this approach in any solution posted so far is the main reason I'm writing this answer ;)


As explained by Score_Under:

# and % delete the shortest possible matching substring from the start and end of the string respectively, and

## and %% delete the longest possible matching substring.

Using the above syntax, we can create an approach where we extract substring "elements" from the string by deleting the substrings up to or after the delimiter.

The codeblock below works well in (including Mac OS's bash), , , , , , and 's :

(Thanks to Adam Katz's comment, making this loop a lot simplier!)


Why not cut?

cut is useful for extracting columns in big files, but doing forks repetitively (var=$(echo ... | cut ...)) become quickly overkill!

Here is a correct syntax, tested under many using cut, as suggested by This other answer from DougW:


Comparing execution time.


Preparing 999 fields:


Then


Where overall execution time is something like 49x longer, using 1 forks to cut, by field, for less than 1'000 fields!!

\t\n'

We can see that the string IN has been stored into an array named fields, split on the semicolons:


(We can also display the contents of these variables using declare -p:)


Note that read is the quickest way to do the split because there are no forks or external resources called.

Once the array is defined, you can use a simple loop to process each field (or, rather, each element in the array you've now defined):


Or you could drop each field from the array after processing using a shifting approach, which I like:


And if you just want a simple printout of the array, you don't even need to loop over it:


Update: recent >= 4.4

In newer versions of bash, you can also play with the command mapfile:


This syntax preserve special chars, newlines and empty fields!

If you don't want to include empty fields, you could do the following:


With mapfile, you can also skip declaring an array and implicitly "loop" over the delimited elements, calling a function on each:


(Note: the \0 at end of the format string is useless if you don't care about empty fields at end of the string or they're not present.)


But you could even use newline (mapfile's default) separator:


Or you could use <<<, and in the function body include some processing to drop the newline it adds:


Split string based on delimiter in

If you can't use bash, or if you want to write something that can be used in many different shells, you often can't use bashisms -- and this includes the arrays we've been using in the solutions above.

However, we don't need to use arrays to loop over "elements" of a string. There is a syntax used in many shells for deleting substrings of a string from the first or last occurrence of a pattern. Note that * is a wildcard that stands for zero or more characters:

(The lack of this approach in any solution posted so far is the main reason I'm writing this answer ;)


As explained by Score_Under:

# and % delete the shortest possible matching substring from the start and end of the string respectively, and

## and %% delete the longest possible matching substring.

Using the above syntax, we can create an approach where we extract substring "elements" from the string by deleting the substrings up to or after the delimiter.

The codeblock below works well in (including Mac OS's bash), , , , , , and 's :

(Thanks to Adam Katz's comment, making this loop a lot simplier!)


Why not cut?

cut is useful for extracting columns in big files, but doing forks repetitively (var=$(echo ... | cut ...)) become quickly overkill!

Here is a correct syntax, tested under many using cut, as suggested by This other answer from DougW:


Comparing execution time.


Preparing 999 fields:


Then


Where overall execution time is something like 49x longer, using 1 forks to cut, by field, for less than 1'000 fields!!

\n'}" -tc 1 -C myPubliMail # Seq: 0: Sending mail to '[email protected]', done. # Seq: 1: Sending mail to '[email protected]', done. # Seq: 2: Sending mail to 'Full Name <[email protected]>', done.

Or you could use <<<, and in the function body include some processing to drop the newline it adds:


Split string based on delimiter in

If you can't use bash, or if you want to write something that can be used in many different shells, you often can't use bashisms -- and this includes the arrays we've been using in the solutions above.

However, we don't need to use arrays to loop over "elements" of a string. There is a syntax used in many shells for deleting substrings of a string from the first or last occurrence of a pattern. Note that * is a wildcard that stands for zero or more characters:

(The lack of this approach in any solution posted so far is the main reason I'm writing this answer ;)


As explained by Score_Under:

# and % delete the shortest possible matching substring from the start and end of the string respectively, and

## and %% delete the longest possible matching substring.

Using the above syntax, we can create an approach where we extract substring "elements" from the string by deleting the substrings up to or after the delimiter.

The codeblock below works well in (including Mac OS's bash), , , , , , and 's :

(Thanks to Adam Katz's comment, making this loop a lot simplier!)


Why not cut?

cut is useful for extracting columns in big files, but doing forks repetitively (var=$(echo ... | cut ...)) become quickly overkill!

Here is a correct syntax, tested under many using cut, as suggested by This other answer from DougW:


Comparing execution time.


Preparing 999 fields:


Then


Where overall execution time is something like 49x longer, using 1 forks to cut, by field, for less than 1'000 fields!!

\t\n'

We can see that the string IN has been stored into an array named fields, split on the semicolons:


(We can also display the contents of these variables using declare -p:)


Note that read is the quickest way to do the split because there are no forks or external resources called.

Once the array is defined, you can use a simple loop to process each field (or, rather, each element in the array you've now defined):


Or you could drop each field from the array after processing using a shifting approach, which I like:


And if you just want a simple printout of the array, you don't even need to loop over it:


Update: recent >= 4.4

In newer versions of bash, you can also play with the command mapfile:


This syntax preserve special chars, newlines and empty fields!

If you don't want to include empty fields, you could do the following:


With mapfile, you can also skip declaring an array and implicitly "loop" over the delimited elements, calling a function on each:


(Note: the \0 at end of the format string is useless if you don't care about empty fields at end of the string or they're not present.)


But you could even use newline (mapfile's default) separator:


Or you could use <<<, and in the function body include some processing to drop the newline it adds:


Split string based on delimiter in

If you can't use bash, or if you want to write something that can be used in many different shells, you often can't use bashisms -- and this includes the arrays we've been using in the solutions above.

However, we don't need to use arrays to loop over "elements" of a string. There is a syntax used in many shells for deleting substrings of a string from the first or last occurrence of a pattern. Note that * is a wildcard that stands for zero or more characters:

(The lack of this approach in any solution posted so far is the main reason I'm writing this answer ;)


As explained by Score_Under:

# and % delete the shortest possible matching substring from the start and end of the string respectively, and

## and %% delete the longest possible matching substring.

Using the above syntax, we can create an approach where we extract substring "elements" from the string by deleting the substrings up to or after the delimiter.

The codeblock below works well in (including Mac OS's bash), , , , , , and 's :

(Thanks to Adam Katz's comment, making this loop a lot simplier!)


Why not cut?

cut is useful for extracting columns in big files, but doing forks repetitively (var=$(echo ... | cut ...)) become quickly overkill!

Here is a correct syntax, tested under many using cut, as suggested by This other answer from DougW:


Comparing execution time.


Preparing 999 fields:


Then


Where overall execution time is something like 49x longer, using 1 forks to cut, by field, for less than 1'000 fields!!

\n'} # drop '\n' added on last field, by '<<<'

With mapfile, you can also skip declaring an array and implicitly "loop" over the delimited elements, calling a function on each:


(Note: the \0 at end of the format string is useless if you don't care about empty fields at end of the string or they're not present.)


But you could even use newline (mapfile's default) separator:


Or you could use <<<, and in the function body include some processing to drop the newline it adds:


Split string based on delimiter in

If you can't use bash, or if you want to write something that can be used in many different shells, you often can't use bashisms -- and this includes the arrays we've been using in the solutions above.

However, we don't need to use arrays to loop over "elements" of a string. There is a syntax used in many shells for deleting substrings of a string from the first or last occurrence of a pattern. Note that * is a wildcard that stands for zero or more characters:

(The lack of this approach in any solution posted so far is the main reason I'm writing this answer ;)


As explained by Score_Under:

# and % delete the shortest possible matching substring from the start and end of the string respectively, and

## and %% delete the longest possible matching substring.

Using the above syntax, we can create an approach where we extract substring "elements" from the string by deleting the substrings up to or after the delimiter.

The codeblock below works well in (including Mac OS's bash), , , , , , and 's :

(Thanks to Adam Katz's comment, making this loop a lot simplier!)


Why not cut?

cut is useful for extracting columns in big files, but doing forks repetitively (var=$(echo ... | cut ...)) become quickly overkill!

Here is a correct syntax, tested under many using cut, as suggested by This other answer from DougW:


Comparing execution time.


Preparing 999 fields:


Then


Where overall execution time is something like 49x longer, using 1 forks to cut, by field, for less than 1'000 fields!!

\t\n'

We can see that the string IN has been stored into an array named fields, split on the semicolons:


(We can also display the contents of these variables using declare -p:)


Note that read is the quickest way to do the split because there are no forks or external resources called.

Once the array is defined, you can use a simple loop to process each field (or, rather, each element in the array you've now defined):


Or you could drop each field from the array after processing using a shifting approach, which I like:


And if you just want a simple printout of the array, you don't even need to loop over it:


Update: recent >= 4.4

In newer versions of bash, you can also play with the command mapfile:


This syntax preserve special chars, newlines and empty fields!

If you don't want to include empty fields, you could do the following:


With mapfile, you can also skip declaring an array and implicitly "loop" over the delimited elements, calling a function on each:


(Note: the \0 at end of the format string is useless if you don't care about empty fields at end of the string or they're not present.)


But you could even use newline (mapfile's default) separator:


Or you could use <<<, and in the function body include some processing to drop the newline it adds:


Split string based on delimiter in

If you can't use bash, or if you want to write something that can be used in many different shells, you often can't use bashisms -- and this includes the arrays we've been using in the solutions above.

However, we don't need to use arrays to loop over "elements" of a string. There is a syntax used in many shells for deleting substrings of a string from the first or last occurrence of a pattern. Note that * is a wildcard that stands for zero or more characters:

(The lack of this approach in any solution posted so far is the main reason I'm writing this answer ;)


As explained by Score_Under:

# and % delete the shortest possible matching substring from the start and end of the string respectively, and

## and %% delete the longest possible matching substring.

Using the above syntax, we can create an approach where we extract substring "elements" from the string by deleting the substrings up to or after the delimiter.

The codeblock below works well in (including Mac OS's bash), , , , , , and 's :

(Thanks to Adam Katz's comment, making this loop a lot simplier!)


Why not cut?

cut is useful for extracting columns in big files, but doing forks repetitively (var=$(echo ... | cut ...)) become quickly overkill!

Here is a correct syntax, tested under many using cut, as suggested by This other answer from DougW:


Comparing execution time.


Preparing 999 fields:


Then


Where overall execution time is something like 49x longer, using 1 forks to cut, by field, for less than 1'000 fields!!

\n'}" -tc 1 -C iterMF }

Preparing 999 fields:


Then


Where overall execution time is something like 49x longer, using 1 forks to cut, by field, for less than 1'000 fields!!

\t\n'

We can see that the string IN has been stored into an array named fields, split on the semicolons:


(We can also display the contents of these variables using declare -p:)


Note that read is the quickest way to do the split because there are no forks or external resources called.

Once the array is defined, you can use a simple loop to process each field (or, rather, each element in the array you've now defined):


Or you could drop each field from the array after processing using a shifting approach, which I like:


And if you just want a simple printout of the array, you don't even need to loop over it:


Update: recent >= 4.4

In newer versions of bash, you can also play with the command mapfile:


This syntax preserve special chars, newlines and empty fields!

If you don't want to include empty fields, you could do the following:


With mapfile, you can also skip declaring an array and implicitly "loop" over the delimited elements, calling a function on each:


(Note: the \0 at end of the format string is useless if you don't care about empty fields at end of the string or they're not present.)


But you could even use newline (mapfile's default) separator:


Or you could use <<<, and in the function body include some processing to drop the newline it adds:


Split string based on delimiter in

If you can't use bash, or if you want to write something that can be used in many different shells, you often can't use bashisms -- and this includes the arrays we've been using in the solutions above.

However, we don't need to use arrays to loop over "elements" of a string. There is a syntax used in many shells for deleting substrings of a string from the first or last occurrence of a pattern. Note that * is a wildcard that stands for zero or more characters:

(The lack of this approach in any solution posted so far is the main reason I'm writing this answer ;)


As explained by Score_Under:

# and % delete the shortest possible matching substring from the start and end of the string respectively, and

## and %% delete the longest possible matching substring.

Using the above syntax, we can create an approach where we extract substring "elements" from the string by deleting the substrings up to or after the delimiter.

The codeblock below works well in (including Mac OS's bash), , , , , , and 's :

(Thanks to Adam Katz's comment, making this loop a lot simplier!)


Why not cut?

cut is useful for extracting columns in big files, but doing forks repetitively (var=$(echo ... | cut ...)) become quickly overkill!

Here is a correct syntax, tested under many using cut, as suggested by This other answer from DougW:


Comparing execution time.


Preparing 999 fields:


Then


Where overall execution time is something like 49x longer, using 1 forks to cut, by field, for less than 1'000 fields!!

\n'} # drop '\n' added on last field, by '<<<'

With mapfile, you can also skip declaring an array and implicitly "loop" over the delimited elements, calling a function on each:


(Note: the \0 at end of the format string is useless if you don't care about empty fields at end of the string or they're not present.)


But you could even use newline (mapfile's default) separator:


Or you could use <<<, and in the function body include some processing to drop the newline it adds:


Split string based on delimiter in

If you can't use bash, or if you want to write something that can be used in many different shells, you often can't use bashisms -- and this includes the arrays we've been using in the solutions above.

However, we don't need to use arrays to loop over "elements" of a string. There is a syntax used in many shells for deleting substrings of a string from the first or last occurrence of a pattern. Note that * is a wildcard that stands for zero or more characters:

(The lack of this approach in any solution posted so far is the main reason I'm writing this answer ;)


As explained by Score_Under:

# and % delete the shortest possible matching substring from the start and end of the string respectively, and

## and %% delete the longest possible matching substring.

Using the above syntax, we can create an approach where we extract substring "elements" from the string by deleting the substrings up to or after the delimiter.

The codeblock below works well in (including Mac OS's bash), , , , , , and 's :

(Thanks to Adam Katz's comment, making this loop a lot simplier!)


Why not cut?

cut is useful for extracting columns in big files, but doing forks repetitively (var=$(echo ... | cut ...)) become quickly overkill!

Here is a correct syntax, tested under many using cut, as suggested by This other answer from DougW:


Comparing execution time.


Preparing 999 fields:


Then


Where overall execution time is something like 49x longer, using 1 forks to cut, by field, for less than 1'000 fields!!

\t\n'

We can see that the string IN has been stored into an array named fields, split on the semicolons:


(We can also display the contents of these variables using declare -p:)


Note that read is the quickest way to do the split because there are no forks or external resources called.

Once the array is defined, you can use a simple loop to process each field (or, rather, each element in the array you've now defined):


Or you could drop each field from the array after processing using a shifting approach, which I like:


And if you just want a simple printout of the array, you don't even need to loop over it:


Update: recent >= 4.4

In newer versions of bash, you can also play with the command mapfile:


This syntax preserve special chars, newlines and empty fields!

If you don't want to include empty fields, you could do the following:


With mapfile, you can also skip declaring an array and implicitly "loop" over the delimited elements, calling a function on each:


(Note: the \0 at end of the format string is useless if you don't care about empty fields at end of the string or they're not present.)


But you could even use newline (mapfile's default) separator:


Or you could use <<<, and in the function body include some processing to drop the newline it adds:


Split string based on delimiter in

If you can't use bash, or if you want to write something that can be used in many different shells, you often can't use bashisms -- and this includes the arrays we've been using in the solutions above.

However, we don't need to use arrays to loop over "elements" of a string. There is a syntax used in many shells for deleting substrings of a string from the first or last occurrence of a pattern. Note that * is a wildcard that stands for zero or more characters:

(The lack of this approach in any solution posted so far is the main reason I'm writing this answer ;)


As explained by Score_Under:

# and % delete the shortest possible matching substring from the start and end of the string respectively, and

## and %% delete the longest possible matching substring.

Using the above syntax, we can create an approach where we extract substring "elements" from the string by deleting the substrings up to or after the delimiter.

The codeblock below works well in (including Mac OS's bash), , , , , , and 's :

(Thanks to Adam Katz's comment, making this loop a lot simplier!)


Why not cut?

cut is useful for extracting columns in big files, but doing forks repetitively (var=$(echo ... | cut ...)) become quickly overkill!

Here is a correct syntax, tested under many using cut, as suggested by This other answer from DougW:


Comparing execution time.


Preparing 999 fields:


Then


Where overall execution time is something like 49x longer, using 1 forks to cut, by field, for less than 1'000 fields!!

\n'}" -tc 1 -C myPubliMail # Seq: 0: Sending mail to '[email protected]', done. # Seq: 1: Sending mail to '[email protected]', done. # Seq: 2: Sending mail to 'Full Name <[email protected]>', done.

Or you could use <<<, and in the function body include some processing to drop the newline it adds:


Split string based on delimiter in

If you can't use bash, or if you want to write something that can be used in many different shells, you often can't use bashisms -- and this includes the arrays we've been using in the solutions above.

However, we don't need to use arrays to loop over "elements" of a string. There is a syntax used in many shells for deleting substrings of a string from the first or last occurrence of a pattern. Note that * is a wildcard that stands for zero or more characters:

(The lack of this approach in any solution posted so far is the main reason I'm writing this answer ;)


As explained by Score_Under:

# and % delete the shortest possible matching substring from the start and end of the string respectively, and

## and %% delete the longest possible matching substring.

Using the above syntax, we can create an approach where we extract substring "elements" from the string by deleting the substrings up to or after the delimiter.

The codeblock below works well in (including Mac OS's bash), , , , , , and 's :

(Thanks to Adam Katz's comment, making this loop a lot simplier!)


Why not cut?

cut is useful for extracting columns in big files, but doing forks repetitively (var=$(echo ... | cut ...)) become quickly overkill!

Here is a correct syntax, tested under many using cut, as suggested by This other answer from DougW:


Comparing execution time.


Preparing 999 fields:


Then


Where overall execution time is something like 49x longer, using 1 forks to cut, by field, for less than 1'000 fields!!

\t\n'

We can see that the string IN has been stored into an array named fields, split on the semicolons:


(We can also display the contents of these variables using declare -p:)


Note that read is the quickest way to do the split because there are no forks or external resources called.

Once the array is defined, you can use a simple loop to process each field (or, rather, each element in the array you've now defined):


Or you could drop each field from the array after processing using a shifting approach, which I like:


And if you just want a simple printout of the array, you don't even need to loop over it:


Update: recent >= 4.4

In newer versions of bash, you can also play with the command mapfile:


This syntax preserve special chars, newlines and empty fields!

If you don't want to include empty fields, you could do the following:


With mapfile, you can also skip declaring an array and implicitly "loop" over the delimited elements, calling a function on each:


(Note: the \0 at end of the format string is useless if you don't care about empty fields at end of the string or they're not present.)


But you could even use newline (mapfile's default) separator:


Or you could use <<<, and in the function body include some processing to drop the newline it adds:


Split string based on delimiter in

If you can't use bash, or if you want to write something that can be used in many different shells, you often can't use bashisms -- and this includes the arrays we've been using in the solutions above.

However, we don't need to use arrays to loop over "elements" of a string. There is a syntax used in many shells for deleting substrings of a string from the first or last occurrence of a pattern. Note that * is a wildcard that stands for zero or more characters:

(The lack of this approach in any solution posted so far is the main reason I'm writing this answer ;)


As explained by Score_Under:

# and % delete the shortest possible matching substring from the start and end of the string respectively, and

## and %% delete the longest possible matching substring.

Using the above syntax, we can create an approach where we extract substring "elements" from the string by deleting the substrings up to or after the delimiter.

The codeblock below works well in (including Mac OS's bash), , , , , , and 's :

(Thanks to Adam Katz's comment, making this loop a lot simplier!)


Why not cut?

cut is useful for extracting columns in big files, but doing forks repetitively (var=$(echo ... | cut ...)) become quickly overkill!

Here is a correct syntax, tested under many using cut, as suggested by This other answer from DougW:


Comparing execution time.


Preparing 999 fields:


Then


Where overall execution time is something like 49x longer, using 1 forks to cut, by field, for less than 1'000 fields!!

\n'} # drop '\n' added on last field, by '<<<'

With mapfile, you can also skip declaring an array and implicitly "loop" over the delimited elements, calling a function on each:


(Note: the \0 at end of the format string is useless if you don't care about empty fields at end of the string or they're not present.)


But you could even use newline (mapfile's default) separator:


Or you could use <<<, and in the function body include some processing to drop the newline it adds:


Split string based on delimiter in

If you can't use bash, or if you want to write something that can be used in many different shells, you often can't use bashisms -- and this includes the arrays we've been using in the solutions above.

However, we don't need to use arrays to loop over "elements" of a string. There is a syntax used in many shells for deleting substrings of a string from the first or last occurrence of a pattern. Note that * is a wildcard that stands for zero or more characters:

(The lack of this approach in any solution posted so far is the main reason I'm writing this answer ;)


As explained by Score_Under:

# and % delete the shortest possible matching substring from the start and end of the string respectively, and

## and %% delete the longest possible matching substring.

Using the above syntax, we can create an approach where we extract substring "elements" from the string by deleting the substrings up to or after the delimiter.

The codeblock below works well in (including Mac OS's bash), , , , , , and 's :

(Thanks to Adam Katz's comment, making this loop a lot simplier!)


Why not cut?

cut is useful for extracting columns in big files, but doing forks repetitively (var=$(echo ... | cut ...)) become quickly overkill!

Here is a correct syntax, tested under many using cut, as suggested by This other answer from DougW:


Comparing execution time.


Preparing 999 fields:


Then


Where overall execution time is something like 49x longer, using 1 forks to cut, by field, for less than 1'000 fields!!

\t\n'

We can see that the string IN has been stored into an array named fields, split on the semicolons:


(We can also display the contents of these variables using declare -p:)


Note that read is the quickest way to do the split because there are no forks or external resources called.

Once the array is defined, you can use a simple loop to process each field (or, rather, each element in the array you've now defined):


Or you could drop each field from the array after processing using a shifting approach, which I like:


And if you just want a simple printout of the array, you don't even need to loop over it:


Update: recent >= 4.4

In newer versions of bash, you can also play with the command mapfile:


This syntax preserve special chars, newlines and empty fields!

If you don't want to include empty fields, you could do the following:


With mapfile, you can also skip declaring an array and implicitly "loop" over the delimited elements, calling a function on each:


(Note: the \0 at end of the format string is useless if you don't care about empty fields at end of the string or they're not present.)


But you could even use newline (mapfile's default) separator:


Or you could use <<<, and in the function body include some processing to drop the newline it adds:


Split string based on delimiter in

If you can't use bash, or if you want to write something that can be used in many different shells, you often can't use bashisms -- and this includes the arrays we've been using in the solutions above.

However, we don't need to use arrays to loop over "elements" of a string. There is a syntax used in many shells for deleting substrings of a string from the first or last occurrence of a pattern. Note that * is a wildcard that stands for zero or more characters:

(The lack of this approach in any solution posted so far is the main reason I'm writing this answer ;)


As explained by Score_Under:

# and % delete the shortest possible matching substring from the start and end of the string respectively, and

## and %% delete the longest possible matching substring.

Using the above syntax, we can create an approach where we extract substring "elements" from the string by deleting the substrings up to or after the delimiter.

The codeblock below works well in (including Mac OS's bash), , , , , , and 's :

(Thanks to Adam Katz's comment, making this loop a lot simplier!)


Why not cut?

cut is useful for extracting columns in big files, but doing forks repetitively (var=$(echo ... | cut ...)) become quickly overkill!

Here is a correct syntax, tested under many using cut, as suggested by This other answer from DougW:


Comparing execution time.


Preparing 999 fields:


Then


Where overall execution time is something like 49x longer, using 1 forks to cut, by field, for less than 1'000 fields!!

\n'}" printf "Seq: %6d: Sending mail to '%s'..." $seq "$dest" # mail -s "This is not a spam..." "$dest" </path/to/body printf "\e[3D, done.\n" } mapfile <<<"$IN" -td \; -c 1 -C myPubliMail # Renders the same output: # Seq: 0: Sending mail to '[email protected]', done. # Seq: 1: Sending mail to '[email protected]', done. # Seq: 2: Sending mail to 'Full Name <[email protected]>', done.

Split string based on delimiter in

If you can't use bash, or if you want to write something that can be used in many different shells, you often can't use bashisms -- and this includes the arrays we've been using in the solutions above.

However, we don't need to use arrays to loop over "elements" of a string. There is a syntax used in many shells for deleting substrings of a string from the first or last occurrence of a pattern. Note that * is a wildcard that stands for zero or more characters:

(The lack of this approach in any solution posted so far is the main reason I'm writing this answer ;)


As explained by Score_Under:

# and % delete the shortest possible matching substring from the start and end of the string respectively, and

## and %% delete the longest possible matching substring.

Using the above syntax, we can create an approach where we extract substring "elements" from the string by deleting the substrings up to or after the delimiter.

The codeblock below works well in (including Mac OS's bash), , , , , , and 's :

(Thanks to Adam Katz's comment, making this loop a lot simplier!)


Why not cut?

cut is useful for extracting columns in big files, but doing forks repetitively (var=$(echo ... | cut ...)) become quickly overkill!

Here is a correct syntax, tested under many using cut, as suggested by This other answer from DougW:


Comparing execution time.


Preparing 999 fields:


Then


Where overall execution time is something like 49x longer, using 1 forks to cut, by field, for less than 1'000 fields!!

\t\n'

We can see that the string IN has been stored into an array named fields, split on the semicolons:


(We can also display the contents of these variables using declare -p:)


Note that read is the quickest way to do the split because there are no forks or external resources called.

Once the array is defined, you can use a simple loop to process each field (or, rather, each element in the array you've now defined):


Or you could drop each field from the array after processing using a shifting approach, which I like:


And if you just want a simple printout of the array, you don't even need to loop over it:


Update: recent >= 4.4

In newer versions of bash, you can also play with the command mapfile:


This syntax preserve special chars, newlines and empty fields!

If you don't want to include empty fields, you could do the following:


With mapfile, you can also skip declaring an array and implicitly "loop" over the delimited elements, calling a function on each:


(Note: the \0 at end of the format string is useless if you don't care about empty fields at end of the string or they're not present.)


But you could even use newline (mapfile's default) separator:


Or you could use <<<, and in the function body include some processing to drop the newline it adds:


Split string based on delimiter in

If you can't use bash, or if you want to write something that can be used in many different shells, you often can't use bashisms -- and this includes the arrays we've been using in the solutions above.

However, we don't need to use arrays to loop over "elements" of a string. There is a syntax used in many shells for deleting substrings of a string from the first or last occurrence of a pattern. Note that * is a wildcard that stands for zero or more characters:

(The lack of this approach in any solution posted so far is the main reason I'm writing this answer ;)


As explained by Score_Under:

# and % delete the shortest possible matching substring from the start and end of the string respectively, and

## and %% delete the longest possible matching substring.

Using the above syntax, we can create an approach where we extract substring "elements" from the string by deleting the substrings up to or after the delimiter.

The codeblock below works well in (including Mac OS's bash), , , , , , and 's :

(Thanks to Adam Katz's comment, making this loop a lot simplier!)


Why not cut?

cut is useful for extracting columns in big files, but doing forks repetitively (var=$(echo ... | cut ...)) become quickly overkill!

Here is a correct syntax, tested under many using cut, as suggested by This other answer from DougW:


Comparing execution time.


Preparing 999 fields:


Then


Where overall execution time is something like 49x longer, using 1 forks to cut, by field, for less than 1'000 fields!!

\n'} # drop '\n' added on last field, by '<<<'

With mapfile, you can also skip declaring an array and implicitly "loop" over the delimited elements, calling a function on each:


(Note: the \0 at end of the format string is useless if you don't care about empty fields at end of the string or they're not present.)


But you could even use newline (mapfile's default) separator:


Or you could use <<<, and in the function body include some processing to drop the newline it adds:


Split string based on delimiter in

If you can't use bash, or if you want to write something that can be used in many different shells, you often can't use bashisms -- and this includes the arrays we've been using in the solutions above.

However, we don't need to use arrays to loop over "elements" of a string. There is a syntax used in many shells for deleting substrings of a string from the first or last occurrence of a pattern. Note that * is a wildcard that stands for zero or more characters:

(The lack of this approach in any solution posted so far is the main reason I'm writing this answer ;)


As explained by Score_Under:

# and % delete the shortest possible matching substring from the start and end of the string respectively, and

## and %% delete the longest possible matching substring.

Using the above syntax, we can create an approach where we extract substring "elements" from the string by deleting the substrings up to or after the delimiter.

The codeblock below works well in (including Mac OS's bash), , , , , , and 's :

(Thanks to Adam Katz's comment, making this loop a lot simplier!)


Why not cut?

cut is useful for extracting columns in big files, but doing forks repetitively (var=$(echo ... | cut ...)) become quickly overkill!

Here is a correct syntax, tested under many using cut, as suggested by This other answer from DougW:


Comparing execution time.


Preparing 999 fields:


Then


Where overall execution time is something like 49x longer, using 1 forks to cut, by field, for less than 1'000 fields!!

\t\n'

We can see that the string IN has been stored into an array named fields, split on the semicolons:


(We can also display the contents of these variables using declare -p:)


Note that read is the quickest way to do the split because there are no forks or external resources called.

Once the array is defined, you can use a simple loop to process each field (or, rather, each element in the array you've now defined):


Or you could drop each field from the array after processing using a shifting approach, which I like:


And if you just want a simple printout of the array, you don't even need to loop over it:


Update: recent >= 4.4

In newer versions of bash, you can also play with the command mapfile:


This syntax preserve special chars, newlines and empty fields!

If you don't want to include empty fields, you could do the following:


With mapfile, you can also skip declaring an array and implicitly "loop" over the delimited elements, calling a function on each:


(Note: the \0 at end of the format string is useless if you don't care about empty fields at end of the string or they're not present.)


But you could even use newline (mapfile's default) separator:


Or you could use <<<, and in the function body include some processing to drop the newline it adds:


Split string based on delimiter in

If you can't use bash, or if you want to write something that can be used in many different shells, you often can't use bashisms -- and this includes the arrays we've been using in the solutions above.

However, we don't need to use arrays to loop over "elements" of a string. There is a syntax used in many shells for deleting substrings of a string from the first or last occurrence of a pattern. Note that * is a wildcard that stands for zero or more characters:

(The lack of this approach in any solution posted so far is the main reason I'm writing this answer ;)


As explained by Score_Under:

# and % delete the shortest possible matching substring from the start and end of the string respectively, and

## and %% delete the longest possible matching substring.

Using the above syntax, we can create an approach where we extract substring "elements" from the string by deleting the substrings up to or after the delimiter.

The codeblock below works well in (including Mac OS's bash), , , , , , and 's :

(Thanks to Adam Katz's comment, making this loop a lot simplier!)


Why not cut?

cut is useful for extracting columns in big files, but doing forks repetitively (var=$(echo ... | cut ...)) become quickly overkill!

Here is a correct syntax, tested under many using cut, as suggested by This other answer from DougW:


Comparing execution time.


Preparing 999 fields:


Then


Where overall execution time is something like 49x longer, using 1 forks to cut, by field, for less than 1'000 fields!!

\n'}" -tc 1 -C myPubliMail # Seq: 0: Sending mail to '[email protected]', done. # Seq: 1: Sending mail to '[email protected]', done. # Seq: 2: Sending mail to 'Full Name <[email protected]>', done.

Or you could use <<<, and in the function body include some processing to drop the newline it adds:


Split string based on delimiter in

If you can't use bash, or if you want to write something that can be used in many different shells, you often can't use bashisms -- and this includes the arrays we've been using in the solutions above.

However, we don't need to use arrays to loop over "elements" of a string. There is a syntax used in many shells for deleting substrings of a string from the first or last occurrence of a pattern. Note that * is a wildcard that stands for zero or more characters:

(The lack of this approach in any solution posted so far is the main reason I'm writing this answer ;)


As explained by Score_Under:

# and % delete the shortest possible matching substring from the start and end of the string respectively, and

## and %% delete the longest possible matching substring.

Using the above syntax, we can create an approach where we extract substring "elements" from the string by deleting the substrings up to or after the delimiter.

The codeblock below works well in (including Mac OS's bash), , , , , , and 's :

(Thanks to Adam Katz's comment, making this loop a lot simplier!)


Why not cut?

cut is useful for extracting columns in big files, but doing forks repetitively (var=$(echo ... | cut ...)) become quickly overkill!

Here is a correct syntax, tested under many using cut, as suggested by This other answer from DougW:


Comparing execution time.


Preparing 999 fields:


Then


Where overall execution time is something like 49x longer, using 1 forks to cut, by field, for less than 1'000 fields!!

\t\n'

We can see that the string IN has been stored into an array named fields, split on the semicolons:


(We can also display the contents of these variables using declare -p:)


Note that read is the quickest way to do the split because there are no forks or external resources called.

Once the array is defined, you can use a simple loop to process each field (or, rather, each element in the array you've now defined):


Or you could drop each field from the array after processing using a shifting approach, which I like:


And if you just want a simple printout of the array, you don't even need to loop over it:


Update: recent >= 4.4

In newer versions of bash, you can also play with the command mapfile:


This syntax preserve special chars, newlines and empty fields!

If you don't want to include empty fields, you could do the following:


With mapfile, you can also skip declaring an array and implicitly "loop" over the delimited elements, calling a function on each:


(Note: the \0 at end of the format string is useless if you don't care about empty fields at end of the string or they're not present.)


But you could even use newline (mapfile's default) separator:


Or you could use <<<, and in the function body include some processing to drop the newline it adds:


Split string based on delimiter in

If you can't use bash, or if you want to write something that can be used in many different shells, you often can't use bashisms -- and this includes the arrays we've been using in the solutions above.

However, we don't need to use arrays to loop over "elements" of a string. There is a syntax used in many shells for deleting substrings of a string from the first or last occurrence of a pattern. Note that * is a wildcard that stands for zero or more characters:

(The lack of this approach in any solution posted so far is the main reason I'm writing this answer ;)


As explained by Score_Under:

# and % delete the shortest possible matching substring from the start and end of the string respectively, and

## and %% delete the longest possible matching substring.

Using the above syntax, we can create an approach where we extract substring "elements" from the string by deleting the substrings up to or after the delimiter.

The codeblock below works well in (including Mac OS's bash), , , , , , and 's :

(Thanks to Adam Katz's comment, making this loop a lot simplier!)


Why not cut?

cut is useful for extracting columns in big files, but doing forks repetitively (var=$(echo ... | cut ...)) become quickly overkill!

Here is a correct syntax, tested under many using cut, as suggested by This other answer from DougW:


Comparing execution time.


Preparing 999 fields:


Then


Where overall execution time is something like 49x longer, using 1 forks to cut, by field, for less than 1'000 fields!!

\n'} # drop '\n' added on last field, by '<<<'

With mapfile, you can also skip declaring an array and implicitly "loop" over the delimited elements, calling a function on each:


(Note: the \0 at end of the format string is useless if you don't care about empty fields at end of the string or they're not present.)


But you could even use newline (mapfile's default) separator:


Or you could use <<<, and in the function body include some processing to drop the newline it adds:


Split string based on delimiter in

If you can't use bash, or if you want to write something that can be used in many different shells, you often can't use bashisms -- and this includes the arrays we've been using in the solutions above.

However, we don't need to use arrays to loop over "elements" of a string. There is a syntax used in many shells for deleting substrings of a string from the first or last occurrence of a pattern. Note that * is a wildcard that stands for zero or more characters:

(The lack of this approach in any solution posted so far is the main reason I'm writing this answer ;)


As explained by Score_Under:

# and % delete the shortest possible matching substring from the start and end of the string respectively, and

## and %% delete the longest possible matching substring.

Using the above syntax, we can create an approach where we extract substring "elements" from the string by deleting the substrings up to or after the delimiter.

The codeblock below works well in (including Mac OS's bash), , , , , , and 's :

(Thanks to Adam Katz's comment, making this loop a lot simplier!)


Why not cut?

cut is useful for extracting columns in big files, but doing forks repetitively (var=$(echo ... | cut ...)) become quickly overkill!

Here is a correct syntax, tested under many using cut, as suggested by This other answer from DougW:


Comparing execution time.


Preparing 999 fields:


Then


Where overall execution time is something like 49x longer, using 1 forks to cut, by field, for less than 1'000 fields!!

\t\n'

We can see that the string IN has been stored into an array named fields, split on the semicolons:


(We can also display the contents of these variables using declare -p:)


Note that read is the quickest way to do the split because there are no forks or external resources called.

Once the array is defined, you can use a simple loop to process each field (or, rather, each element in the array you've now defined):


Or you could drop each field from the array after processing using a shifting approach, which I like:


And if you just want a simple printout of the array, you don't even need to loop over it:


Update: recent >= 4.4

In newer versions of bash, you can also play with the command mapfile:


This syntax preserve special chars, newlines and empty fields!

If you don't want to include empty fields, you could do the following:


With mapfile, you can also skip declaring an array and implicitly "loop" over the delimited elements, calling a function on each:


(Note: the \0 at end of the format string is useless if you don't care about empty fields at end of the string or they're not present.)


But you could even use newline (mapfile's default) separator:


Or you could use <<<, and in the function body include some processing to drop the newline it adds:


Split string based on delimiter in

If you can't use bash, or if you want to write something that can be used in many different shells, you often can't use bashisms -- and this includes the arrays we've been using in the solutions above.

However, we don't need to use arrays to loop over "elements" of a string. There is a syntax used in many shells for deleting substrings of a string from the first or last occurrence of a pattern. Note that * is a wildcard that stands for zero or more characters:

(The lack of this approach in any solution posted so far is the main reason I'm writing this answer ;)


As explained by Score_Under:

# and % delete the shortest possible matching substring from the start and end of the string respectively, and

## and %% delete the longest possible matching substring.

Using the above syntax, we can create an approach where we extract substring "elements" from the string by deleting the substrings up to or after the delimiter.

The codeblock below works well in (including Mac OS's bash), , , , , , and 's :

(Thanks to Adam Katz's comment, making this loop a lot simplier!)


Why not cut?

cut is useful for extracting columns in big files, but doing forks repetitively (var=$(echo ... | cut ...)) become quickly overkill!

Here is a correct syntax, tested under many using cut, as suggested by This other answer from DougW:


Comparing execution time.


Preparing 999 fields:


Then


Where overall execution time is something like 49x longer, using 1 forks to cut, by field, for less than 1'000 fields!!

╰◇生如夏花灿烂 2025-02-16 06:43:46

这对我有用:

string="1;2"
echo $string | cut -d';' -f1 # output is 1
echo $string | cut -d';' -f2 # output is 2

This worked for me:

string="1;2"
echo $string | cut -d';' -f1 # output is 1
echo $string | cut -d';' -f2 # output is 2
街道布景 2025-02-16 06:43:46

我认为 awk 是解决问题的最佳和有效命令。默认情况下,几乎每个Linux发行版都包含尴尬。

echo "[email protected];[email protected]" | awk -F';' '{print $1,$2}'

当然,您可以

[email protected] [email protected]

通过重新定义尴尬打印字段来存储每个电子邮件地址。

I think AWK is the best and efficient command to resolve your problem. AWK is included by default in almost every Linux distribution.

echo "[email protected];[email protected]" | awk -F';' '{print $1,$2}'

will give

[email protected] [email protected]

Of course your can store each email address by redefining the awk print field.

我一直都在从未离去 2025-02-16 06:43:46

该方法如何:

IN="[email protected];[email protected]" 
set -- "$IN" 
IFS=";"; declare -a Array=($*) 
echo "${Array[@]}" 
echo "${Array[0]}" 
echo "${Array[1]}" 

source

How about this approach:

IN="[email protected];[email protected]" 
set -- "$IN" 
IFS=";"; declare -a Array=($*) 
echo "${Array[@]}" 
echo "${Array[0]}" 
echo "${Array[1]}" 

Source

唠甜嗑 2025-02-16 06:43:46

这也有效:

IN="[email protected];[email protected]"
echo ADD1=`echo $IN | cut -d \; -f 1`
echo ADD2=`echo $IN | cut -d \; -f 2`

要小心,此解决方案并不总是正确的。如果您通过“ 对add1和add2均可进行。

This also works:

IN="[email protected];[email protected]"
echo ADD1=`echo $IN | cut -d \; -f 1`
echo ADD2=`echo $IN | cut -d \; -f 2`

Be careful, this solution is not always correct. In case you pass "[email protected]" only, it will assign it to both ADD1 and ADD2.

故事↓在人 2025-02-16 06:43:46

Darron的答案我这样做:

IN="[email protected];[email protected]"
read ADDR1 ADDR2 <<<$(IFS=";"; echo $IN)

A different take on Darron's answer, this is how I do it:

IN="[email protected];[email protected]"
read ADDR1 ADDR2 <<<$(IFS=";"; echo $IN)
长不大的小祸害 2025-02-16 06:43:46

如果您不使用数组,该衬里怎么样:

IFS=';' read ADDR1 ADDR2 <<<$IN

How about this one liner, if you're not using arrays:

IFS=';' read ADDR1 ADDR2 <<<$IN
生活了然无味 2025-02-16 06:43:46

在bash中,即使您的变量包含newlines:

IFS=';' read -d '' -ra array < <(printf '%s;\0' "$in")

look:

$ in=

工作的诀窍是使用 -d 选项 read (定界符)带有一个空的定界符,因此读取被迫读取其馈送的所有内容。而且,我们将读取添加中的变量的内容,借助 printf ,没有尾随的新线。请注意,这也是我们还将定界符放在 printf 中,以确保将字符串传递到 read 具有落后定界符。没有它,读取将修剪潜在的尾随空字段:

$ in='one;two;three;'    # there's an empty field
$ IFS=';' read -d '' -ra array < <(printf '%s;\0' "$in")
$ declare -p array
declare -a array='([0]="one" [1]="two" [2]="three" [3]="")'

保留了尾随的空字段。


BASH≥4.4的更新

由于Bash 4.4,因此内置 mapfile (aka readarray )支持> -D 选项,以指定定界符。因此,另一种规范的方式是:

mapfile -d ';' -t array < <(printf '%s;' "$in")
one;two three;*;there is\na newline\nin this field' $ IFS=';' read -d '' -ra array < <(printf '%s;\0' "$in") $ declare -p array declare -a array='([0]="one" [1]="two three" [2]="*" [3]="there is a newline in this field")'

工作的诀窍是使用 -d 选项 read (定界符)带有一个空的定界符,因此读取被迫读取其馈送的所有内容。而且,我们将读取添加中的变量的内容,借助 printf ,没有尾随的新线。请注意,这也是我们还将定界符放在 printf 中,以确保将字符串传递到 read 具有落后定界符。没有它,读取将修剪潜在的尾随空字段:


保留了尾随的空字段。


BASH≥4.4的更新

由于Bash 4.4,因此内置 mapfile (aka readarray )支持> -D 选项,以指定定界符。因此,另一种规范的方式是:


In Bash, a bullet proof way, that will work even if your variable contains newlines:

IFS=';' read -d '' -ra array < <(printf '%s;\0' "$in")

Look:

$ in=

The trick for this to work is to use the -d option of read (delimiter) with an empty delimiter, so that read is forced to read everything it's fed. And we feed read with exactly the content of the variable in, with no trailing newline thanks to printf. Note that's we're also putting the delimiter in printf to ensure that the string passed to read has a trailing delimiter. Without it, read would trim potential trailing empty fields:

$ in='one;two;three;'    # there's an empty field
$ IFS=';' read -d '' -ra array < <(printf '%s;\0' "$in")
$ declare -p array
declare -a array='([0]="one" [1]="two" [2]="three" [3]="")'

the trailing empty field is preserved.


Update for Bash≥4.4

Since Bash 4.4, the builtin mapfile (aka readarray) supports the -d option to specify a delimiter. Hence another canonical way is:

mapfile -d ';' -t array < <(printf '%s;' "$in")
one;two three;*;there is\na newline\nin this field' $ IFS=';' read -d '' -ra array < <(printf '%s;\0' "$in") $ declare -p array declare -a array='([0]="one" [1]="two three" [2]="*" [3]="there is a newline in this field")'

The trick for this to work is to use the -d option of read (delimiter) with an empty delimiter, so that read is forced to read everything it's fed. And we feed read with exactly the content of the variable in, with no trailing newline thanks to printf. Note that's we're also putting the delimiter in printf to ensure that the string passed to read has a trailing delimiter. Without it, read would trim potential trailing empty fields:


the trailing empty field is preserved.


Update for Bash≥4.4

Since Bash 4.4, the builtin mapfile (aka readarray) supports the -d option to specify a delimiter. Hence another canonical way is:



    
苏佲洛 2025-02-16 06:43:46

如果您只有一个结肠,则不设置IF,

您可以做到:

a="foo:bar"
b=${a%:*}
c=${a##*:}

您将得到:

b = foo
c = bar

Without setting the IFS

If you just have one colon you can do that:

a="foo:bar"
b=${a%:*}
c=${a##*:}

you will get:

b = foo
c = bar
悟红尘 2025-02-16 06:43:46

这是一个干净的3线:

in="foo@bar;bizz@buzz;fizz@buzz;buzz@woof"
IFS=';' list=($in)
for item in "${list[@]}"; do echo $item; done

其中 ifs 基于分隔符的划界单词和()用于创建 array 。然后, [@] 用于将每个项目作为单独的单词返回。

如果您之后有任何代码,您还需要还原 $ ifs ,例如未设置IFS

Here is a clean 3-liner:

in="foo@bar;bizz@buzz;fizz@buzz;buzz@woof"
IFS=';' list=($in)
for item in "${list[@]}"; do echo $item; done

where IFS delimit words based on the separator and () is used to create an array. Then [@] is used to return each item as a separate word.

If you've any code after that, you also need to restore $IFS, e.g. unset IFS.

三生池水覆流年 2025-02-16 06:43:46

这么多的答案和如此多的复杂性。尝试一个更简单的解决方案:

echo "string1, string2" | tr , "\n"

tr (读取,翻译)将第一个参数替换为输入中的第二个参数。

因此

string1
string2

So many answers and so many complexities. Try out a simpler solution:

echo "string1, string2" | tr , "\n"

tr (read, translate) replaces the first argument with the second argument in the input.

So tr , "\n" replace the comma with new line character in the input and it becomes:

string1
string2
ぇ气 2025-02-16 06:43:46

以下bash/zsh函数将其第一个参数分配在第二个参数给出的定界符上:

split() {
    local string="$1"
    local delimiter="$2"
    if [ -n "$string" ]; then
        local part
        while read -d "$delimiter" part; do
            echo $part
        done <<< "$string"
        echo $part
    fi
}

例如,命令

$ split 'a;b;c' ';'

产生的

a
b
c

输出可能会将其管道输送到其他命令。示例:

$ split 'a;b;c' ';' | cat -n
1   a
2   b
3   c

与给出的其他解决方案相比,该解决方案具有以下优点:

  • ifs 并不是过度的:由于局部变量的动态范围,覆盖了 ,循环导致新值泄漏到从循环内执行的函数调用。

  • 不使用数组:使用读取在bash中读取 -a 的 -a 在zsh中需要flag -a 。

如果需要,可以将功能放入脚本中,如下所示:

#!/usr/bin/env bash

split() {
    # ...
}

split "$@"

The following Bash/zsh function splits its first argument on the delimiter given by the second argument:

split() {
    local string="$1"
    local delimiter="$2"
    if [ -n "$string" ]; then
        local part
        while read -d "$delimiter" part; do
            echo $part
        done <<< "$string"
        echo $part
    fi
}

For instance, the command

$ split 'a;b;c' ';'

yields

a
b
c

This output may, for instance, be piped to other commands. Example:

$ split 'a;b;c' ';' | cat -n
1   a
2   b
3   c

Compared to the other solutions given, this one has the following advantages:

  • IFS is not overriden: Due to dynamic scoping of even local variables, overriding IFS over a loop causes the new value to leak into function calls performed from within the loop.

  • Arrays are not used: Reading a string into an array using read requires the flag -a in Bash and -A in zsh.

If desired, the function may be put into a script as follows:

#!/usr/bin/env bash

split() {
    # ...
}

split "$@"
东走西顾 2025-02-16 06:43:46

有这样一个简单而聪明的方式:

echo "add:sfff" | xargs -d: -i  echo {}

但是您必须使用GNU Xargs,BSD Xargs Cath Cath Cath -D DeLim。如果您使用像我这样的苹果Mac。您可以安装GNU Xargs:

brew install findutils

然后

echo "add:sfff" | gxargs -d: -i  echo {}

There is a simple and smart way like this:

echo "add:sfff" | xargs -d: -i  echo {}

But you must use gnu xargs, BSD xargs cant support -d delim. If you use apple mac like me. You can install gnu xargs :

brew install findutils

then

echo "add:sfff" | gxargs -d: -i  echo {}
爱人如己 2025-02-16 06:43:46

在许多情况下应用尴尬

echo "[email protected];[email protected]"|awk -F';' '{printf "%s\n%s\n", $1, $2}'

您也可以

echo "[email protected];[email protected]"|awk -F';' '{print $1,$2}' OFS="\n"

you can apply awk to many situations

echo "[email protected];[email protected]"|awk -F';' '{printf "%s\n%s\n", $1, $2}'

also you can use this

echo "[email protected];[email protected]"|awk -F';' '{print $1,$2}' OFS="\n"
温柔嚣张 2025-02-16 06:43:46

这里有一些很酷的答案(尤其是错误的),但是对于类似于其他语言的东西,这是我最初的问题的意思 - 我对此进行了解决:

IN="[email protected];[email protected]"
declare -a a="(${IN//;/ })";

现在 $ {a [a [0] } $ {a [1]} 等,如您所期望的。使用 $ {#a [*]} 用于术语数。当然,要进行迭代:

for i in ${a[*]}; do echo $i; done

重要说明:

这在无需担心空间的情况下起作用,这解决了我的问题,但可能无法解决您的问题。在这种情况下,请使用 $ ifs 解决方案。

There are some cool answers here (errator esp.), but for something analogous to split in other languages -- which is what I took the original question to mean -- I settled on this:

IN="[email protected];[email protected]"
declare -a a="(${IN//;/ })";

Now ${a[0]}, ${a[1]}, etc, are as you would expect. Use ${#a[*]} for number of terms. Or to iterate, of course:

for i in ${a[*]}; do echo $i; done

IMPORTANT NOTE:

This works in cases where there are no spaces to worry about, which solved my problem, but may not solve yours. Go with the $IFS solution(s) in that case.

攀登最高峰 2025-02-16 06:43:46

这是最简单的方法。

spo='one;two;three'
OIFS=$IFS
IFS=';'
spo_array=($spo)
IFS=$OIFS
echo ${spo_array[*]}

This is the simplest way to do it.

spo='one;two;three'
OIFS=$IFS
IFS=';'
spo_array=($spo)
IFS=$OIFS
echo ${spo_array[*]}
昔日梦未散 2025-02-16 06:43:46

如果没有空间,为什么不这样做呢?

IN="[email protected];[email protected]"
arr=(`echo $IN | tr ';' ' '`)

echo ${arr[0]}
echo ${arr[1]}

If no space, Why not this?

IN="[email protected];[email protected]"
arr=(`echo $IN | tr ';' ' '`)

echo ${arr[0]}
echo ${arr[1]}
心碎无痕… 2025-02-16 06:43:46

简单答案:

IN="[email protected];[email protected]"

IFS=';' read ADDR1 ADDR2 <<< "${IN}"

样本输出:

echo "${ADDR1}"  # prints "[email protected]"
echo "${ADDR2}"  # prints "[email protected]"

Simple answer:

IN="[email protected];[email protected]"

IFS=';' read ADDR1 ADDR2 <<< "${IN}"

Sample output:

echo "${ADDR1}"  # prints "[email protected]"
echo "${ADDR2}"  # prints "[email protected]"
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文