Shell编程基础(十)读取多行文本到数组 & 写入多行文本到文件

读取多行文本到数组 & 写入多行文本到文件

读取多行文本到数组

创建一个文本文件,内容如下

1 zhangsan 男 10
2 liis  女 12
3 wangwu 男 17

读取这个文件中所有人的信息

#!/bin/bash
while read u
do
echo $u
done < ./test.txt

上述shell,执行顺序:

  1. 读取文本内容给到 while 循环
  2. while循环将每一行数据交给 read
  3. 由 read 将每一行的数据 给到 变量 u
  4. 最终实现遍历

按性别统计人数

#!/bin/bash
declare -A count_by_sex
while read u
do
sex=`echo $u | awk '{print $3}'`
# 第一种. 分步定义统计变量
#count=`echo $[${count_by_sex[$sex]}+1]`
#count_by_sex[$sex]=`echo $count`

# 第二种. 直接使用数组自增
#let count_by_sex[$sex]++

# 第三种. 将第一种方法融合成一条
count_by_sex[$sex]=`echo $[${count_by_sex[$sex]}+1]`
done < ./test.txt

for i in ${!count_by_sex[@]}
do
echo $i : ${count_by_sex[$i]}
done

写入多行文本到文件

#!/bin/bash
echo "1
2
3
4" > echo_lines.txt

cat <<-FFF > cat_lines.txt
1
2
3
4
FFF

以上两种都能将指定格式的数据写入文本。

需要注意的是
echo 方式引号如果没和数据在一行,会有一个空行

cat 方式说明
<< 表示将FFF 中定义的内容收集到 cat 中
FFF 定义多行文本结束符,通常这个标识符使用 EOF(end of file)并非只能EOF
>/>> cat_lines.txt 将cat 收集到的文本以覆盖/追加的方式重定向到文件 cat_lines.txt 中

&lt;think&gt;嗯,用户现在想了解在Shell脚本中如何按行读取多行文本变量。我之前已经回答过关于从文件读取的问题,但这次用户是处理变量中的多行文本。我需要调整之前的思路,从处理文件转向处理变量内容。 首先,用户提到的是&ldquo;多行文本变量&rdquo;,也就是变量里存储了多行数据,比如通过命令替换或者直接赋值得到的。例如,var=&quot;line1\nline2\nline3&quot;。这时候,如何逐行处理这个变量中的内容呢? 在之前的回答中,我提到了修改IFS和使用循环的方法,但那是针对从文件读取的情况。现在需要处理变量里的内容,可能需要类似的方法,但需要调整输入源。比如,用here-string或者管道将变量内容传递给循环。 然后,我需要考虑用户可能的误区。比如,直接使用for循环可能会因为IFS默认的分隔符导致按空格分割而不是换行。所以,必须设置IFS为换行符。同时,处理变量中的换行符是否正确,比如是否使用$&#39;&#39;的转义方式。 接下来,用户可能需要具体的示例。我需要给出两种主要方法:使用while read循环和数组遍历。这两种方法各有优缺点,需要比较说明。比如,while read更通用,处理大文本更高效,而数组方法可能适合较小的数据。 另外,需要注意变量作用域的问题。比如,在管道中使用while read时,循环体内的变量修改可能不会影响到父shell,所以需要避免这种情况,使用进程替换或者here-string来保持作用域。 然后,要检查引用中的内容是否有帮助。引用[2]提到了循环读取文件的方法,但用户现在处理的是变量,可能需要调整这些方法。引用[1]和[3]关于变量的定义和使用,可能需要注意变量赋值时的引号使用,避免分词问题。 可能的问题点:用户的多行变量是否正确赋值?例如,是否使用了双引号和换行符。比如,正确的方式是var=$&#39;line1\nline2&#39;,或者在赋值时直接换行。需要示例中展示正确的变量赋值方式。 另外,是否需要处理特殊字符,比如包含空格或制表符的行。这时候,read命令的-r参数和双引号变量引用很重要,要提醒用户使用这些选项来保留原始内容。 最后,总结不同方法的适用场景,帮助用户根据具体情况选择。比如,处理大文本变量时推荐while循环,小数据可以用数组。同时,提供注意事项,比如IFS的修改、作用域问题、特殊字符处理等。 可能还需要回答用户潜在的问题,比如如何将命令输出的多行内容存储到变量中,然后逐行处理。例如,使用var=$(command)来捕获输出,然后处理。这时候要注意命令输出中的换行符是否正确保留。 总结,我需要分步骤给出两种方法,并详细说明每个步骤的注意事项,提供示例,并比较优缺点,最后列出常见问题及解决方法,确保用户能够正确应用。&lt;/think&gt;在 Shell 脚本中按行读取多行文本变量,核心思路是 **通过字段分隔符(IFS)控制分割方式**,并结合循环结构逐行处理。以下是具体方法分类和完整实现示例: --- ### 方法 1:通过 `while read` 逐行读取(推荐) **适用场景**:多行文本变量包含特殊字符(空格、制表符、引号等)或需要逐行处理 **原理**:利用 `read` 命令的逐行读取特性,通过 `&lt;&lt;&lt;`(here-string)将变量内容作为输入流 ```bash #!/bin/bash # 定义多行文本变量 multiline_var=&quot;line1 line2 with spaces line3 &#39;special&#39; \&quot;characters\&quot;&quot; # 逐行读取并处理 while IFS= read -r line; do echo &quot;[处理行]: $line&quot; done &lt;&lt;&lt; &quot;$multiline_var&quot; ``` **输出**: ``` [处理行]: line1 [处理行]: line2 with spaces [处理行]: line3 &#39;special&#39; &quot;characters&quot; ``` **关键参数说明**: - `IFS=`:清空字段分隔符,避免行首/尾空格被截断[^1] - `-r`:禁用反斜杠转义,保留原始内容[^3] - `&lt;&lt;&lt; &quot;$multiline_var&quot;`:将变量内容作为输入流传递给 `while` 循环 --- ### 方法 2:通过数组分割读取(小文本适用) **适用场景**:已知文本不含特殊符号且需随机访问行内容 **原理**:设置 `IFS` 为换行符,将多行变量转换为数组 ```bash #!/bin/bash multiline_var=&quot;apple banana cherry&quot; IFS=$&#39;\n&#39; # 设置换行符为分隔符 lines=($multiline_var) # 将变量转换为数组 for line in &quot;${lines[@]}&quot;; do echo &quot;水果: $line&quot; done ``` **输出**: ``` 水果: apple 水果: banana 水果: cherry ``` **注意事项**: - 若变量中存在通配符(如`*`),需先禁用路径扩展:`set -f`[^3] - 数组会一次性加载所有内容,**不适合大文本** --- ### 方法 3:结合 `printf` 格式化输出 **适用场景**:动态生成多行内容并处理 **示例**: ```bash #!/bin/bash # 生成多行内容(例如命令输出) multiline_var=$(printf &quot;item-%d\n&quot; {1..3}) # 逐行处理 while read -r item; do echo &quot;生成项: $item&quot; done &lt;&lt;&lt; &quot;$multiline_var&quot; ``` **输出**: ``` 生成项: item-1 生成项: item-2 生成项: item-3 ``` --- ### 关键问题与解决方案 | 问题场景 | 解决方案 | |---------------------------|--------------------------------------------------------------------------| | 行内包含空格/制表符 | 使用 `while IFS= read -r` 保留完整行内容[^1] | | 变量中存在通配符(如`*`) | 在数组转换前执行 `set -f`,处理完恢复 `set +f` | | 需要修改外部变量 | 使用 `&lt;&lt;&lt;` 替代管道(避免子 Shell 作用域隔离) | | 处理 Windows 换行符(CRLF)| 先转换文本格式:`multiline_var=${multiline_var//$&#39;\r&#39;/}` | --- ### 性能对比 | 方法 | 内存占用 | 特殊字符支持 | 适用场景 | |------------|----------|--------------|------------------------| | `while read` | 低 | 支持 | 通用场景(尤其是大文本)| | 数组分割 | 高 | 有限 | 小文本快速访问 | --- ### 相关问题 1. 如何在循环中跳过空行? - 在 `read` 后添加条件判断:`[[ -n &quot;$line&quot; ]] || continue` 2. 如何统计多行变量的总行数? - 使用 `wc -l &lt;&lt;&lt; &quot;$multiline_var&quot;` 3. 如何将多行变量写入文件并保持格式? - `printf &quot;%s\n&quot; &quot;$multiline_var&quot; &gt; output.txt` 如需处理文件内容与变量的混合操作,可参考:[Shell 文本处理三剑客深度解析](https://example.com)[^2][^3]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值