Đầu vào:
1
hgh
h2b
h4h
2
ok
koko
lkopk
3
uh
ju
nfjvn
4
Sản lượng dự kiến:
1
2
3
4
Vì vậy, tôi chỉ cần có giá trị thứ 1, 5, 9, 13 của tệp trong tệp đầu ra. làm như thế nào?
Đầu vào:
1
hgh
h2b
h4h
2
ok
koko
lkopk
3
uh
ju
nfjvn
4
Sản lượng dự kiến:
1
2
3
4
Vì vậy, tôi chỉ cần có giá trị thứ 1, 5, 9, 13 của tệp trong tệp đầu ra. làm như thế nào?
Câu trả lời:
Sử dụng AWK:
awk '!((NR - 1) % 4)' input > output
Tìm hiểu làm thế nào điều này hoạt động là một bài tập cho người đọc.
NR % 4 == 1IMO dễ đọc hơn.
Sử dụng split (GNU coreutils):
split -nr/1/4 input > output
-ntạo CHUNKStập tin đầu ravà CHUNKSnhư
r/K/N sử dụng phân phối vòng tròn và chỉ xuất Kth của N để xuất chuẩn mà không tách dòng / bản ghiVới GNU sed:
sed '1~4!d' < input > output
Với tiêu chuẩn sed:
sed -n 'p;n;n;n' < input > output
Với 1và 4trong $nvà $icác biến:
sed "$n~$i!d" # GNU only
awk -v n="$n" -v i="$i" 'NR >= n && (NR % i) == (n % i)'
Phiên bản Python, chỉ để giải trí:
with open('input.txt') as f:
for i, line in enumerate(f.readlines()):
if i%4 == 0:
print(line.strip())
enumerate(f)sẽ có thể thực hiện công việc trong khi tiêu thụ ít bộ nhớ hơn
readlines(do đó đưa toàn bộ tệp vào bộ nhớ), bạn có thể sử dụng f.readlines()[::4]để nhận mọi dòng thứ tư. Vì vậy, bạn có thể sử dụng print(''.join(f.readlines()[::4])).
POSIX sed: phương pháp này sử dụng sed posixly và do đó có thể được chạy ở mọi nơi, hoặc ít nhất là những sed đó tôn trọng posix.
$ sed -ne '
/\n/!{
H;s/.*//;x
}
:loop
$bdone
N;s/\n/&/4
tdone
bloop
:done
s/.//;P
' input.file
Một cái khác là tạo mã sed lập trình cho mục đích mở rộng:
$ code=$(yes n | head -n 4 | paste -sd\; | sed s/n/p/)
$ sed -ne "$code" input.file
Perl: chúng tôi điền vào mảng A cho đến khi nó có kích thước 4. Sau đó, chúng tôi in phần tử đầu tiên của nó và cũng xóa mảng.
$ perl -pe '
$A[@A] = @A ? <> : $_ while @A < 4;
$_ = (splice @A)[0];
' input.file
Gọi với scriptname filename skip(4 trong trường hợp của bạn) Nó hoạt động bằng cách kéo itercác dòng từ đầu tệp và sau đó chỉ xuất ra cuối cùng. Nó sau đó từng bước iterbởi skipsvà lặp đi lặp lại chừng nào giá trị của iterkhông vượt quá linestrong file.
#!/bin/bash
file="$1"
lines=`wc -l < "$file"`
skips="$2" || "4"
iter=1
while [ "$iter" -le "$lines" ]; do
head "$file" -n $iter | tail -n 1
iter=$(( $iter + $skips ))
done
Bash thuần túy:
mapfile -t lines < input
for (( i=0; i < ${#lines[@]}; i+=4 ))
do printf "%s\n" "${lines[$i]}"
done
mapfile là một nội dung được thêm vào trong Bash 4, đọc đầu vào tiêu chuẩn vào một mảng, được đặt tên ở đây lines, với một dòng trên mỗi mục nhập. Các -ttùy chọn dải các dòng mới cuối cùng.
Nếu bạn muốn in mọi dòng thứ tư bắt đầu từ dòng 4, thì bạn có thể thực hiện điều đó trong một lệnh bằng mapfiletùy chọn gọi lại -C, chạy mã được cung cấp mỗi rất nhiều dòng, với khoảng thời gian được cung cấp bởi -c. Chỉ mục mảng hiện tại và dòng tiếp theo được gán được cung cấp cho mã dưới dạng đối số.
mapfile -t -c4 -C 'printf "%.0s%s\n"' < input
Điều này sử dụng printfnội dung; mã định dạng %.0sngăn chặn đối số đầu tiên (chỉ mục), do đó chỉ có dòng được in.
Bạn có thể sử dụng cùng một lệnh để in mọi dòng thứ tư bắt đầu từ dòng 1, 2 hoặc 3, nhưng bạn phải đặt trước 3, 2 hoặc 1 dòng inputtrước khi đưa nó vào mapfile, điều mà tôi nghĩ là rắc rối hơn giá trị của nó .
Điều này cũng hoạt động:
mapfile -t lines < input
printf "%s%.0s%.0s%.0s\n" "${lines[@]}"
Ở đây, printftiêu thụ bốn mục của mảng linestại một thời điểm, chỉ in lần đầu tiên và bỏ qua ba mục còn lại với %.0s. Tôi không thích điều này vì bạn phải tự chỉnh sửa chuỗi định dạng cho các khoảng thời gian hoặc điểm bắt đầu khác nhau.
sed -n '1~4p'