shell脚本:嵌套while循环:不拾取外循环计数器

发布于 2024-12-09 13:20:02 字数 1185 浏览 0 评论 0原文

我有一个包含数百万条记录的文件。我将在这里用两个示例记录来简化它。我的目标是添加分隔符(例如逗号),以使文件具有相同数量的分隔符,以便我可以将文件上传到数据库。

问题在于嵌套的 while 循环只是在行尾添加了固定数量的分隔符。我的目标是根据文件已有的分隔符数量动态添加分隔符。我将内部 while 循环更改为 if 语句块,也发生了相同的行为。所以我认为嵌套的 while 循环是没有必要的。

这是我的示例文本文件:

1st,1,
2nd,2

这是脚本。第一个用户输入位置是文本文件,第二个位置是我想要的分隔符数量。

#!/bin/bash

f="$1"
delim="$2"

while read line
do
cnt=`echo $line | tr -cd ',' | wc -c`
    while   [[ $cnt  -lt $delim ]];   
    do
            sed -i 's/$/,/' $f 
        cnt=`expr $cnt + 1`
    done
done  < $f

这是我使用 bash -x 的跟踪:

bash -x csv.sh split_address_2.csv 3
+ f=split_address_2.csv
+ delim=3
+ read line
++ wc -c
++ tr -cd ,
++ echo 1st,1,
+ cnt=2
+ [[ 2 -lt 3 ]]
+ sed -i 's/$/,/' split_address_2.csv
++ expr 2 + 1
+ cnt=3
+ [[ 3 -lt 3 ]]
+ read line
++ wc -c
++ tr -cd ,
++ echo 2nd,2
+ cnt=1
+ [[ 1 -lt 3 ]]
+ sed -i 's/$/,/' split_address_2.csv
++ expr 1 + 1
+ cnt=2
+ [[ 2 -lt 3 ]]
+ sed -i 's/$/,/' split_address_2.csv
++ expr 2 + 1
+ cnt=3
+ [[ 3 -lt 3 ]]
+ read line

这是文本文件的输出。您可以看到该脚本只是在每行末尾添加了 3 个逗号。

1st,1,,,,
2nd,2,,,

非常感谢您的友好回复。祝你有美好的一天!

I have a file that has millions of records. I will just make it simple with two sample records here. My goal is to add delimiters, such as a comma, to make the file has the same number of delimiters, so I can upload the file to a database.

The issue is that the nested while loop simply added a fixed number of delimiters at the end of line. My goal is to add delimiters dynamically according to the number of delimiters the file already has. I changed the inner while loop to a if statement block, the same behavior happened as well. So I do not think a nested while loop is necessary.

Here is my sample text file:

1st,1,
2nd,2

Here is the script. First user input position is the text file, the second position is the number of delimiters I want.

#!/bin/bash

f="$1"
delim="$2"

while read line
do
cnt=`echo $line | tr -cd ',' | wc -c`
    while   [[ $cnt  -lt $delim ]];   
    do
            sed -i 's/$/,/' $f 
        cnt=`expr $cnt + 1`
    done
done  < $f

Here is my trace using bash -x:

bash -x csv.sh split_address_2.csv 3
+ f=split_address_2.csv
+ delim=3
+ read line
++ wc -c
++ tr -cd ,
++ echo 1st,1,
+ cnt=2
+ [[ 2 -lt 3 ]]
+ sed -i 's/$/,/' split_address_2.csv
++ expr 2 + 1
+ cnt=3
+ [[ 3 -lt 3 ]]
+ read line
++ wc -c
++ tr -cd ,
++ echo 2nd,2
+ cnt=1
+ [[ 1 -lt 3 ]]
+ sed -i 's/$/,/' split_address_2.csv
++ expr 1 + 1
+ cnt=2
+ [[ 2 -lt 3 ]]
+ sed -i 's/$/,/' split_address_2.csv
++ expr 2 + 1
+ cnt=3
+ [[ 3 -lt 3 ]]
+ read line

Here is the output of the text file. You can see the script simply added 3 commas at the end of each line.

1st,1,,,,
2nd,2,,,

Thanks so much for your kind response. Have a good day!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

九命猫 2024-12-16 13:20:02

为什么在这里使用 sed -i ?通过该命令,您正在对整个文件的每一行进行搜索和替换...

在输入文件的第一行中,已经有 2 个逗号,因此您的 while 循环运行一次,将每一行附加到您的输入文件带有额外的逗号。在第二行,只有一个逗号,因此 while 循环运行两次,在整个文本中的每一行附加 2 个额外的逗号。这就是为什么运行脚本时每行后面有 3 个额外的逗号。

我对你的脚本做了一些简单的小调整。这次它按您的预期工作:

#!/bin/bash

f="$1"
delim="$2"

while read line
do
cnt=`echo $line | tr -cd ',' | wc -c`
    while   [[ $cnt  -lt $delim ]];   
    do
        line=`echo $line | sed 's/$/,/'`
        cnt=`expr $cnt + 1`
    done
    echo $line
done  < $f

Why did you use sed -i here? By that command, you are doing a search and replace on your whole file there, on each line...

In your first line in your input file, there are already 2 commas, so your while-loop runs once, appending each line in your input file with an extra comma. On the second line, there's only one comma so your while-loop runs twice, appending each line in your your whole text with 2 extra comma. That's why there are 3 extra commas after each line when you have run your script.

I did some simple minor adjustment to your script. It works as your expected this time:

#!/bin/bash

f="$1"
delim="$2"

while read line
do
cnt=`echo $line | tr -cd ',' | wc -c`
    while   [[ $cnt  -lt $delim ]];   
    do
        line=`echo $line | sed 's/$/,/'`
        cnt=`expr $cnt + 1`
    done
    echo $line
done  < $f
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文