Bash 根据行号将一个文件划分为单独的文件
我有以下测试文件:Bash 根据行号将一个文件划分为单独的文件,bash,awk,Bash,Awk,我有以下测试文件: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 我希望以一种方式将其分开,即每个文件都包含上一个文件的最后一行作为第一行。例如: file 1: 1 2 3 4 5 file2: 5 6 7 8 9 file3: 9 10 11 12 13 file4: 13 14 15 16 17 file5: 17 18 19 20 这将使4个文件有5行,1个文件有4行 作为第一步,我尝试测试我编写的以下命令,以仅获取包含前5行
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
我希望以一种方式将其分开,即每个文件都包含上一个文件的最后一行作为第一行。例如:
file 1:
1
2
3
4
5
file2:
5
6
7
8
9
file3:
9
10
11
12
13
file4:
13
14
15
16
17
file5:
17
18
19
20
这将使4个文件有5行,1个文件有4行
作为第一步,我尝试测试我编写的以下命令,以仅获取包含前5行的第一个文件。我不明白为什么if
语句中的awk
命令不打印前5行,而是打印整个20行
d=$(wc test)
a=$(echo $d | cut -f1 -d " ")
lines=$(echo $a/5 | bc -l)
integer=$(echo $lines | cut -f1 -d ".")
for i in $(seq 1 $integer); do
start=$(echo $i*5 | bc -l)
var=$((var+=1))
echo start $start
echo $var
if [[ $var = 1 ]]; then
awk 'NR<=$start' test
fi
done
d=$(wc测试)
a=$(回声$d |切-f1-d“”)
行=$(回声$a/5 | bc-l)
整数=$(回显$行|切-f1-d“。)
对于以美元表示的i(seq 1$整数);做
开始=$(回声$i*5 | bc-l)
var=$((var+=1))
echo start$start
echo$var
如果[[$var=1]];然后
awk'NR为什么不直接使用您的POSIX
工具包中提供的split
util呢。它有一个按行数拆分的选项,您可以按5
split -l 5 input-file
从人员拆分
页面
-l, --lines=NUMBER
put NUMBER lines/records per output file
请注意,-l
也是。为什么不直接使用POSIX
工具包中提供的split
util呢。它有一个按行数拆分的选项,您可以按5
split -l 5 input-file
从人员拆分
页面
-l, --lines=NUMBER
put NUMBER lines/records per output file
请注意,-l
也是
如果您试图再次使用shell循环来操作文本,请确保先阅读,以了解至少一些使用awk的原因。要学习awk,请阅读Arnold Robbins的《有效的awk编程》,第四版
哦。并说明为什么您的awk命令awk'NR
如果您试图再次使用shell循环来操作文本,请确保先阅读,以了解至少一些使用awk的原因。要学习awk,请阅读Arnold Robbins的《有效的awk编程》,第四版
哦。请解释为什么您的awk命令awk'NR您可以通过删除不必要的echo
cut
和bc
来改进您的代码,并像这样做
#!/bin/bash
for i in $(seq $(wc -l < test) ); do
(( i % 4 != 1 )) && continue
tail +$i test | head -5 > "file$(( 1+i/4 ))"
done
#/bin/bash
对于以美元表示的i(seq$(wc-l“文件$((1+i/4))”
完成
但awk解决方案仍然要好得多。只读取一次文件,并根据随时可用的信息(如行号)采取措施是一种方法。在shell中,你必须数数行,没有办法绕过它awk
将免费为您提供这些(以及许多其他东西) 您可以通过删除不必要的echo
cut
和bc
来改进代码,并按如下方式执行
#!/bin/bash
for i in $(seq $(wc -l < test) ); do
(( i % 4 != 1 )) && continue
tail +$i test | head -5 > "file$(( 1+i/4 ))"
done
#/bin/bash
对于以美元表示的i(seq$(wc-l“文件$((1+i/4))”
完成
但awk解决方案仍然要好得多。只读取一次文件,并根据随时可用的信息(如行号)采取措施是一种方法。在shell中,你必须数数行,没有办法绕过它awk
将免费为您提供这些(以及许多其他东西) 使用拆分:
$ seq 20 | split -l 5
$ for fn in x*; do echo "$fn"; cat "$fn"; done
xaa
1
2
3
4
5
xab
6
7
8
9
10
xac
11
12
13
14
15
xad
16
17
18
19
20
或者,如果您有文件:
$ split -l test_file
使用拆分:
$ seq 20 | split -l 5
$ for fn in x*; do echo "$fn"; cat "$fn"; done
xaa
1
2
3
4
5
xab
6
7
8
9
10
xac
11
12
13
14
15
xad
16
17
18
19
20
或者,如果您有文件:
$ split -l test_file
你试过拆分吗?@123我添加了一个编辑,解释了这一点。@Ed Morton很抱歉搞混了。我最初的目标是sthg else(现在已在编辑版本中解释),但我只想问代码中的bug,所以我写了不同的问题。现在,我希望它更清晰。FYI获取文件中的行数,而不是d=$(wc test);a=$(echo$d | cut-f1-d“”)
您只需执行a=$(wc
。此外,学习始终引用shell变量对您来说非常重要。除非您需要双引号来达到特定目的,否则请使用单引号;除非您不需要双引号,否则请使用双引号。引号不是您需要时选择添加的内容,而是您不需要添加时选择不添加的内容。您是否尝试过拆分?@123我添加了一个编辑,解释了这一点。@Ed Morton很抱歉造成混淆。我最初的目标是sthg else(现在已在编辑版本中解释),但我只想问代码中的bug,所以我写了不同的问题。现在,我希望它更清晰。FYI获取文件中的行数,而不是d=$(wc test);a=$(echo$d | cut-f1-d“”)
您只需执行a=$(wc
。此外,学习始终引用shell变量对您来说非常重要。除非您需要双引号来达到特定目的,否则请使用单引号;除非您不需要双引号,否则请使用双引号。引号不是你需要时选择添加的东西,而是你不需要添加时选择不添加的东西;这是POSIX授权的实用程序。@Jens:是的!,不知道,我打了;)最初的问题基本上是“每4行打印文件中的5行”,其中包括行的重叠,这是拆分无法做到的;这是POSIX授权的实用程序。@Jens:是的!,不知道,我打了;)最初的问题基本上是“每4行打印文件中的5行”,其中包括行的重叠,这是拆分无法做到的。