2017-05-05 40 views
0

我有以下的測試文件:將一個文件分成單獨的基於行號

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 

謝謝!

+0

你試過'split'? – 123

+0

@ 123我添加了一個解釋這個的編輯。 – Homap

+0

@Ed Morton對不起,感到困惑。我最初的目標是sthg else(現在在編輯版本中解釋過),但我只想詢問我的代碼中的錯誤,所以我寫了不同的問題。現在,我希望它更清楚。 – Homap

回答

2
$ ls 
$ 
$ seq 20 | awk 'NR%4==1{ if (out) { print > out; close(out) } out="file"++c } {print > out}' 
$ 
$ ls 
file1 file2 file3 file4 file5 

$ cat file1 
1 
2 
3 
4 
5 
$ cat file2 
5 
6 
7 
8 
9 
$ cat file3 
9 
10 
11 
12 
13 
$ cat file4 
13 
14 
15 
16 
17 
$ cat file5 
17 
18 
19 
20 

如果你曾經嘗試使用一個shell循環再處理文本,請務必閱讀https://unix.stackexchange.com/questions/169716/why-is-using-a-shell-loop-to-process-text-considered-bad-practice第一至少了解一些原因,而不是AWK使用。要學習awk,請閱讀Arnold Robbins編寫的第4版Effective Awk Programming。

哦。並且爲什麼你的awk命令awk 'NR<=$start' test不起作用 - awk不是shell,它沒有比C程序更多的對shell變量的訪問(反之亦然)。要使用名爲start的shell變量的值初始化一個名爲awkstart的awk變量,然後在腳本中使用該awk變量,那麼將執行awk -v awkstart="$start" 'NR<=awkstart' test。 awk變量也可以被命名爲start或其他任何明智的東西 - 它與shell變量的名稱完全無關。

3

爲什麼不使用POSIX工具包中提供的split util。它有一個選項分裂的行數,你可以把它作爲5

split -l 5 input-file 

man split頁面,

-l, --lines=NUMBER 
     put NUMBER lines/records per output file 

需要注意的是,-lPOSIX compliant也。

+0

Nit挑選:分裂不是一個bash的事情;這是POSIX強制實用程序。 – Jens

+0

@Jens:是的,不知道我輸入了它;) – Inian

+0

原來的問題,基本上是'每4行打印5行',包含了行重疊,這是行不通的。 – ULick

0

你可以通過刪除unneccesary echocutbc提高你的代碼,並像這樣做

#!/bin/bash 
for i in $(seq $(wc -l < test)); do 
    ((i % 4 != 1)) && continue 
    tail +$i test | head -5 > "file$((1+i/4))" 
done 

但還是awk的解決方案要好得多。只讀取一次文件,並根據現成的信息(如牀單編號)採取行動是一條路。在外殼必須計算線路,有沒有辦法繞過它。 awk會免費給你(和很多其他的東西)。

0

使用split

$ 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 
相關問題