5

我有一个文本文件,其中包含由空文本行分隔的文本行。我想将该文件的内容推送到一个数组中,并使用空行作为分隔符。我尝试了 IFS="\n" (或 "\r\n" 等。)但无法让它工作,所以我想我会用不在文件中的字符替换任何空行,所以我拿起了西班牙倒置问号 (\xBF)

sed 's/^$/'$(echo -e "\xBF")'/'))

这样就行了,我有一个字符,我将用它来分割我的文件并将其放入一个数组中。(有点随机技巧,但嘿,这只是一种方法..)

现在我需要更改 $IFS 以便它使用倒置的问号来分割数组的数据。

如果我输入

IFS=$(echo -e "\xBF")

在命令行中它工作得很好

 echo "$IFS"
¿

但是,如果我键入带有尾随 read -a 的命令,那么它什么也不做:

[user@machine ~]$ IFS=$(echo -e "\xBF") read -a array <<< "$var"
[user@machine ~]$ echo "$IFS"
[user@machine ~]$

这很奇怪,因为 $var 有一个值。

更令人惊讶的是,当我在得到以下信息后立即验证 IFS 的值时:

[user@machine ~]$ echo -n "$IFS" | od -abc
0000000  sp  ht  nl
    040 011 012
         \t  \n
0000003
[user@machine ~]$ 

这是 IFS 的默认值。

我很确定 IFS 可以使用任何字符,不是吗?

或者,如果您有任何技巧可以根据空行拆分数组中的文件,我很感兴趣!(为了理解起见,我仍然想深入了解这一点)。

非常感谢,周末愉快:)

4

2 回答 2

5

这个脚本应该做你想做的事:

#!/bin/bash

i=1
s=1
declare -a arr
while read -r line 
do
    # If we find an empty line, then we increase the counter (i), 
    # set the flag (s) to one, and skip to the next line
    [[ $line == "" ]] && ((i++)) && s=1 && continue 

    # If the flag (s) is zero, then we are not in a new line of the block
    # so we set the value of the array to be the previous value concatenated
    # with the current line
    [[ $s == 0 ]] && arr[$i]="${arr[$i]}
$line" || { 
            # Otherwise we are in the first line of the block, so we set the value
            # of the array to the current line, and then we reset the flag (s) to zero 
            arr[$i]="$line"
            s=0; 
    }
done < file

for i in "${arr[@]}"
do
   echo "================"
   echo "$i"
done 

测试文件:

$ cat file
asdf dsf s dfsdaf s
sadfds fdsa fads f dsaf as

fdsafds f dsf ds afd f saf dsf
sdfsfs dfadsfsaf

sdfsafds fdsafads fd saf adsfas
sdfdsfds fdsfd saf dsa fds fads f

输出:

================
asdf dsf s dfsdaf s
sadfds fdsa fads f dsaf as
================
fdsafds f dsf ds afd f saf dsf
sdfsfs dfadsfsaf
================
sdfsafds fdsafads fd saf adsfas
sdfdsfds fdsfd saf dsa fds fads f

更新:

为了忽略以 开头的行#,您可以在 之后添加此行do

[[ $line =~ ^# ]] && continue
于 2013-08-30T18:54:38.817 回答
4

首先,根据设计,设置为的变量var=foo command仅对脚本的其余部分可用,command而不会为脚本的其余部分设置。

至于您的问题,read读取记录直到第一个分隔符(-d,默认值:换行符),然后将其拆分为$IFS.

要遍历您的项目,您可以使用

sed -e 's/^$/\xBF/' | while read -d $'\xBF' var
do
    printf "Value: %s\n-----\n" "$var"
done

要将它们全部从字符串读入数组,您可以一直读取到某个您希望没有的字符,例如 NUL 字节:

IFS=$'\xBF' read -d '' -a array <<< "$var"
于 2013-08-30T18:47:18.057 回答