Đầ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 == 1
IMO dễ đọc hơn.
Sử dụng split
(GNU coreutils):
split -nr/1/4 input > output
-n
tạo CHUNKS
tập tin đầu ravà CHUNKS
như
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 1
và 4
trong $n
và $i
cá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 iter
các dòng từ đầu tệp và sau đó chỉ xuất ra cuối cùng. Nó sau đó từng bước iter
bởi skips
và lặp đi lặp lại chừng nào giá trị của iter
không vượt quá lines
trong 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 -t
tù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 mapfile
tù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 printf
nội dung; mã định dạng %.0s
ngă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 input
trướ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, printf
tiêu thụ bốn mục của mảng lines
tạ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'