BASH字符串处理:字符串分割为数组

本文详细介绍了Bash和Java在字符串处理方面的差异,包括字符串分割、数组定义与使用方法,以及如何在Bash中实现类似Java的字符串操作。

http://codingstandards.iteye.com/blog/1164910

Bash字符串处理(与Java对照) - 25.字符串分割(成数组)

In Java

String.split

 String[]     split(String regex)
          根据给定的正则表达式的匹配来拆分此字符串。
 String[]     split(String regex, int limit)
          根据匹配给定的正则表达式来拆分此字符串。

 

In Bash

简单介绍一下Bash中的数组的定义和使用方法

在Bash中,每个变量都可以作为一维数组使用,并且Bash也只支持一维数组。

$VAR等同于${VAR[0]}

 

还有一种多此一举的声明数组的方法:declare -a VAR

 

数组数据的设置方式有:

VAR=(v1 v2 v3)

VAR=([0]=v0 [1]=v1 [2]=v2)

VAR[0]=v0

 

引用数组元素的方式:

$VAR  ${VAR}  ${VAR[0]}  第0个元素

${VAR[n]}  第n个元素(n从0开始计算)

 

引用整个数组:

${VAR[*]}  ${VAR[*]}   这两种方式等同,会把数组展开。

"${VAR[*]}"  表示把数组拼接在一起的整个字符串,如果作为参数传递,会把整个字符串作为一个参数。

"${VAR[@]}"  如果作为参数传递,表示把数组中每个元素作为一个参数,数组有多少个元素,就会展开成多少个参数。

 

计算数组元素长度:

${#VAR[*]}  ${#VAR[@]}   不是 ${#VAR},因为它等同于 ${#VAR[0]}


注意:数组元素长度 != 最大索引 + 1,因为Bash的数组是稀疏数组(Sparse array)。

[root@web ~]# a[1]=1 
[root@web ~]# a[1000]=1000 
[root@web ~]# declare -p a 
declare -a a='([1]="1" [1000]="1000")'
[root@web ~]# echo "$a" 

[root@web ~]# echo "$a[1]" 
[1]
[root@web ~]# echo "${a[@]}" 
1 1000
[root@web ~]# echo "${#a[@]}" 
2
[root@web ~]#

 

遍历数组元素:(注意双引号)

for ELEM in "${ARRAY[@]}"

do

    echo $ELEM

done

 

以空白作为分隔符来拆分字符串构造数组

ARR=($STR)

注意$STR不能加引号。

 

[root@jfht ~]# STR="Hello World" 
[root@jfht ~]# ARR=($STR) 
[root@jfht ~]# declare -p ARR 
declare -a ARR='([0]="Hello" [1]="World")'
[root@jfht ~]#

 

用指定分隔符来拆分字符串构造数组

如果分隔符不是空白,而是别的,那么需要借助IFS变量。

default IFS (Internal Field Separator, which is space/tab/new line)

 

[root@jfht ~]# echo $PATH 
/usr/kerberos/sbin:/usr/kerberos/bin:/usr/apache/apache-ant-1.7.1/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
[root@jfht ~]# IFS=: DIRS=($PATH) 
[root@jfht ~]# declare -p DIRS   
declare -a DIRS='([0]="/usr/kerberos/sbin" [1]="/usr/kerberos/bin" [2]="/usr/apache/apache-ant-1.7.1/bin" [3]="/usr/local/sbin" [4]="/usr/local/bin" [5]="/sbin" [6]="/bin" [7]="/usr/sbin" [8]="/usr/bin" [9]="/root/bin")'
[root@jfht ~]#

 

但是下面的方式是不行的。

[root@jfht ~]# echo $PATH 
/usr/kerberos/sbin:/usr/kerberos/bin:/usr/apache/apache-ant-1.7.1/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
[root@jfht ~]# IFS=: declare -a DIRS=($PATH) 
[root@jfht ~]# declare -p DIRS 
declare -a DIRS='([0]="/usr/kerberos/sbin:/usr/kerberos/bin:/usr/apache/apache-ant-1.7.1/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin")'
[root@jfht ~]#

 

使用read -a来拆分字符串构造数组

All work and no play makes Jack a dull boy.
只会用功不玩耍,聪明孩子也变傻。

 

[root@jfht ~]# PROVERB="All work and no play makes Jack a dull boy." 
[root@jfht ~]# read -a WORDS <<<$PROVERB 
[root@jfht ~]# echo "$WORDS" 
All
[root@jfht ~]# echo "${#WORDS}" 
3

[root@jfht ~]# echo "${WORDS[*]}" 
All work and no play makes Jack a dull boy.
[root@jfht ~]# echo "${WORDS[@]}" 
All work and no play makes Jack a dull boy.
[root@jfht ~]# echo "${#WORDS[*]}" 
10
[root@jfht ~]# echo "${#WORDS[@]}" 
10

 

前面的例子中要分割的字符串是以空格分割的,现在举一个以:分割的例子。

[root@jfht ~]# echo $IFS 

[root@jfht ~]# IFS=: read -r -a DIRS <<<"$PATH" 
[root@jfht ~]# echo $IFS 

[root@jfht ~]# declare -p DIRS 
declare -a DIRS='([0]="/usr/kerberos/sbin" [1]="/usr/kerberos/bin" [2]="/usr/apache/apache-ant-1.7.1/bin" [3]="/usr/local/sbin" [4]="/usr/local/bin" [5]="/sbin" [6]="/bin" [7]="/usr/sbin" [8]="/usr/bin" [9]="/root/bin")'
[root@jfht ~]# 

 

下面的例子是将当前工作目录以/进行分割。

[root@jfht ctmw]# echo $PWD 
/root/work191/ct08/src/ctmw
[root@jfht ctmw]# IFS=/ read -r -a PARTS <<<$PWD 
[root@jfht ctmw]# declare -p PARTS 
declare -a PARTS='([0]=" root work191 ct08 src ctmw")'
[root@jfht ctmw]# 
[root@jfht ctmw]# IFS=/ read -r -a PARTS <<<"$PWD" 
[root@jfht ctmw]# declare -p PARTS                 
declare -a PARTS='([0]="" [1]="root" [2]="work191" [3]="ct08" [4]="src" [5]="ctmw")'
[root@jfht ctmw]#

 

使用cut命令分隔字符串

echo "$STR" | cut -f $N

以TAB分隔,打印第N个子串值,N从1开始计数。

echo "$STR" | cut -d "$DELIM" -d $N

以指定DELIM分隔,打印第N个子串值,N从1开始计数。

其中,-d部分也可以是$N1,$N2,$N3的形式,即输出多个子串。

 

A good beginning is half done.
良好的开端是成功的一半。

 

[root@jfht ~]# STR="A good beginning is half done." 
[root@jfht ~]# echo $STR | cut -d ' ' -f 2          
good

 

[root@jfht ~]# echo $PATH 
/usr/kerberos/sbin:/usr/kerberos/bin:/usr/apache/apache-ant-1.7.1/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
[root@jfht ~]# echo $PATH | cut -d ':' -f 3 
/usr/apache/apache-ant-1.7.1/bin

[root@jfht ~]# echo $PATH | cut -d ':' -f 3,5 
/usr/apache/apache-ant-1.7.1/bin:/usr/local/bin

 

使用awk命令分隔字符串

echo "$STR" | awk '{print $1}'

echo "$STR" | awk '{print $2}'

注意:awk后面的参数用单引号,不能用双引号。

 

[root@jfht ~]# STR="A good beginning is half done." 
[root@jfht ~]# echo "$STR" | awk '{print $1}' 
A
[root@jfht ~]# echo "$STR" | awk '{print $2}' 
good
[root@jfht ~]# echo "$STR" | awk '{print $5,$6}' 
half done.

 

 

 

 

<think>我们参考了用户提供的引用内容,但用户的问题是关于在Shell脚本中如何将字符串拆分为数组。根据用户的问题,我们需要提供在Shell脚本中分割字符串数组的方法。 在Bash中,我们可以使用内置的`read`命令或者数组赋值语法来实现字符串分割。 方法1:使用`read`命令(如引用[1]所述) read命令可以从标准输入读取一行,并根据IFS(Internal Field Separator)的值将其分割成多个字段,然后赋值给指定的变量(如果是数组则使用-a选项)。 方法2:直接使用数组赋值语法 在Bash中,我们可以直接将字符串赋值给数组,此时字符串会根据IFS的值自动分割。 另外,我们还可以通过设置IFS来改变分割行为。 下面我们通过示例来展示这些方法。</think>### Shell脚本中将字符串拆分为数组的方法 在Shell脚本中,可以使用以下方法将字符串拆分为数组: #### 1. 使用`read`命令(推荐方法) ```bash # 示例字符串 str="apple banana cherry" # 使用read命令分割数组 IFS=' ' read -ra my_array <<< "$str" # 验证结果 echo "数组元素数量: ${#my_array[@]}" for fruit in "${my_array[@]}"; do echo "水果: $fruit" done ``` 输出: ``` 数组元素数量: 3 水果: apple 水果: banana 水果: cherry ``` #### 2. 直接赋值给数组变量 ```bash # 示例字符串 str="Linux macOS Windows" # 直接赋值创建数组 os_array=($str) # 访问元素 echo "第一个系统: ${os_array[0]}" # 输出: 第一个系统: Linux echo "所有系统: ${os_array[@]}" # 输出: 所有系统: Linux macOS Windows ``` #### 3. 自定义分隔符(使用IFS) ```bash # 示例CSV数据 csv_data="John,Doe,30,New York" # 设置分隔符为逗号 IFS=',' read -ra person <<< "$csv_data" # 访问字段 echo "姓名: ${person[0]} ${person[1]}" echo "年龄: ${person[2]}" echo "城市: ${person[3]}" ``` #### 4. 处理带空格的元素 ```bash # 包含空格的字符串 str='item1 "item 2" item3' # 安全分割方法 eval "array=($str)" # 验证结果 echo "元素1: ${array[0]}" # 输出: item1 echo "元素2: ${array[1]}" # 输出: item 2 ``` #### 重要技术细节: 1. **IFS(内部字段分隔符)** 默认值为空格、制表符、换行符,可通过修改实现自定义分割: ```bash IFS=':' read -ra path_array <<< "$PATH" ``` 2. **带引号的元素处理** 使用`eval`可保留引号内的空格: ```bash str='Hello "World of Shell"' eval "words=($str)" echo "${words[1]}" # 输出: World of Shell ``` 3. **数组操作技巧** ```bash # 获取数组长度 echo "元素数量: ${#my_array[@]}" # 遍历数组 for item in "${my_array[@]}"; do echo "处理: $item" done # 访问特定元素 echo "第一个: ${my_array[0]}" echo "最后一个: ${my_array[-1]}" ``` 4. **多行字符串处理** ```bash multi_line="apple\nbanana\ncherry" readarray -t fruits <<< "$(echo -e "$multi_line")" ``` > **安全注意事项** > - 使用`eval`时要确保输入安全,避免代码注入风险 > - 处理用户输入时优先使用`read -r`防止反斜杠转义[^1] > - 复杂数据结构建议使用`jq`工具处理JSON数据
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值