从文件中读取行,并使用Bash以特定格式输出

时间:2017-09-25 18:55:03

标签: bash variables while-loop concat

在A.csv中,有

1
2
3
4

我应该如何阅读此文件并创建变量$B$C,以便:

echo $B
echo $C

返回:

1 2 3 4 
1,2,3,4

到目前为止,我正在尝试:

cat A.csv | while read A;

do

echo $A

done

只返回

1
2
3
4

6 个答案:

答案 0 :(得分:2)

假设bash 4.x,以下是高效,健壮和原生的:

# Read each line of A.csv into a separate element of the array lines
readarray -t lines <A.csv

# Generate a string B with a comma after each item in the array
printf -v B '%s,' "${lines[@]}"

# Prune the last comma from that string
B=${B%,}

# Generate a string C with a space after each item in the array
printf -v B '%s ' "${lines[@]}"

答案 1 :(得分:1)

echo "$B"

输出:

1 2 3 4

引用:

merge

输出:

1
2
3
4

答案 2 :(得分:1)

正如@Cyrus所说

B=$(cat A.csv)
echo $B

将输出:

1 2 3 4

因为如果变量没有用引号括起来,bash不会带有换行符。如果A.csv包含可能受bash glob扩展影响的任何字符,那么这很危险,但如果你只是阅读简单字符串就应该没问题。

如果您正在阅读任何元素中没有空格的简单字符串,您还可以使用以下内容获得$ C所需的结果:

echo $B | tr ' ' ','

这将输出:

1,2,3,4

如果A.csv中的行可能包含bash特殊字符或空格,那么我们将返回循环。

为什么我像我一样格式化文件读取循环,请参阅:Looping through the content of a file in Bash?

B=''
C=''
while read -u 7 curr_line; do
  if [ "$B$C" == "" ]; then
    B="$curr_line"
    C="$curr_line"
  else
    B="$B $curr_line"
    C="$C,$curr_line"
  fi
done 7<A.csv

echo "$B"
echo "$C"

将根据需要使用循环遍历文件内容构造两个变量,并防止不必要的通配和拆分。

答案 3 :(得分:1)

我会把文件读成一个bash数组:

mapfile -t array < A.csv

然后,使用各种连接字符

b="${array[*]}"     # space is the default
echo "$b"

c=$( IFS=","; echo "${array[*]}" )
echo "$c"

或者,您可以使用paste加入具有指定分隔符的所有行:

b=$( paste -d" " -s < A.csv )
c=$( paste -d"," -s < A.csv )

答案 4 :(得分:0)

试试这个:

cat A.csv | while read A;

do

printf "$A"

done

问候!

答案 5 :(得分:0)

试试这个(更简单的一个):

b=$(tr '\n' ' ' < file)
c=$(tr '\n' ',' < file)

您不必为此阅读文件。确保运行dos2unix file命令。如果您在Windows中运行(要删除\r)。

注意: 它会修改文件。因此,请确保您从原始文件中复制。