如何在 Bash 中将两个字符串(包括用逗号分隔的空格)存储到两个单独的文件中



>第二次在这里发帖。如果我在格式上犯了任何错误,我深表歉意。 我有一个文件,其中包含一个美国州及其各自的首都,旁边用逗号分隔。

Alabama,Montgomery
Alaska,Juneau
Arizona,Phoenix
Arkansas,Little Rock
California,Sacramento
Colorado,Denver

我正在尝试将州和城市分成两个单独的文件,并设法提出了这个,

for line in $(cat file);do
capital=$(echo $line | cut -d , -f2)
state=$(echo $line | cut -d , -f1)
echo $capital >> capitals
echo $state >> states
done

这段代码的问题在于,即使我将剪切分隔符设置为逗号,该程序似乎仍有空间作为包含空格的城市的分隔符(例如小石城(。

使用我上面的程序,我的大写文件包含,

Montgomery
Juneau
Phoenix
Little
Rock
Sacramento
Denver

请注意,小石城在两行中,而不是在同一行中。如何修改我的程序以使其在同一行中?我尝试将 IFS 设置为逗号,但当我这样做时,我的大写文件也包含状态。

Alabama
Montgomery
Alaska
Juneau
Arizona
Phoenix
Arkansas
Little Rock
California
Sacramento
Colorado
Denver

如果您同意awk,请您尝试以下操作。

awk '
BEGIN{
FS=","
out_city="city_output_file"
out_state="state_output_file"
}
{
print $1 > (out_state)
print $2 > (out_city)
}
'  Input_file

bash

while IFS=, read -r  state city;
do
echo "$state" >> "state_output_file"
echo "$city" >> "city_output_file"
done < "Input_file"

虽然awk可以解决这个问题,但您还应该了解如何在 shell 脚本中读取文件并使用参数扩展来修剪每行中不需要的文本,以隔离状态和大写字母,并将每个文本写入各自的文件。

它是 shell 脚本的基本面包和黄油部分。(这里很容易(例如:

#!/bin/bash
states=${2:-states}         ## states as 2nd argument (default "states")
capitals=${3:-capitals}     ## capitals as 3rd argument (default "capitals")
:>$states       ## truncate both files
:>$capitals
while read -r line || [ -n "$line" ]; do
echo "${line%,*}" >> "$states"     ## trim line from right to 1st comma
echo "${line#*,}" >> "$capitals"   ## trim line from left to 1st comma
done < "$1"

(注意:脚本从作为程序第一个参数提供的文件名读取,并写入状态和首都文件(可选(作为第二个和第三个参数提供(

示例输入文件

$ cat file
Alabama,Montgomery
Alaska,Juneau
Arizona,Phoenix
Arkansas,Little Rock
California,Sacramento
Colorado,Denver

使用示例

$ bash separate.sh file

生成的输出文件

国家:

$ cat states
Alabama
Alaska
Arizona
Arkansas
California
Colorado

资本:

$ cat capitals
Montgomery
Juneau
Phoenix
Little Rock
Sacramento
Denver

awk会更快,但上面的脚本将比您每次迭代管道输出到cut生成多个子壳的原始尝试效率高几个数量级。仔细查看,如果您有其他问题,请告诉我。

添加合并文件

我想您还希望在单独的行上为州和首都提供一个合并文件。只需为输出添加另一个文件,例如

#!/bin/bash
states=${2:-states}         ## states as 2nd argument (default "states")
capitals=${3:-capitals}     ## capitals as 3rd argument (default "capitals")
combined=${4:-combined}     ## combined as 4th argument (default "combined")
:>$states       ## truncate all files
:>$capitals
:>$combined
while read -r line || [ -n "$line" ]; do
echo "${line%,*}" >> "$states"     ## trim line from right to 1st comma
echo "${line#*,}" >> "$capitals"   ## trim line from left to 1st comma
printf "%sn%sn" "${line%,*}" "${line#*,}" >> "$combined"
done < "$1"

(注意:|| [ -n "$line" ]添加到while循环条件将处理没有POSIX文件结尾的最后一行('n'在最后一行的末尾((

生成的输出文件

组合的:

$ cat combined
Alabama
Montgomery
Alaska
Juneau
Arizona
Phoenix
Arkansas
Little Rock
California
Sacramento
Colorado
Denver

无需为输入的每一行创建六个子进程。如果输入文件变得非常大,这将花费大量的挂钟时间。我会做的

cut -d , -f2 file > capitals
cut -d , -f1 file > states

无需为输入的每一行创建六个子进程。如果输入文件很大,那么它很有用

awk -F ',' '{print $(NF-1)}' > capital file
awk -F ',' '{print $NF}' > states file

最新更新