Tôi có một số tập tin như thế này:
abc 123
abc 789
bcd 456
acb 135
Tôi muốn in cột đầu tiên của dòng tiếp theo trong dòng hiện tại.
Sản phẩm chất lượng:
abc 123 abc
abc 789 bcd
bcd 456 acb
acb 135
Tôi thích sử dụng awk.
Tôi có một số tập tin như thế này:
abc 123
abc 789
bcd 456
acb 135
Tôi muốn in cột đầu tiên của dòng tiếp theo trong dòng hiện tại.
Sản phẩm chất lượng:
abc 123 abc
abc 789 bcd
bcd 456 acb
acb 135
Tôi thích sử dụng awk.
Câu trả lời:
Ghi nhớ dòng trước:
awk 'NR > 1 { print prev, $1 } { prev = $0 } END { print prev }'
Quá trình này xử lý đầu vào như sau:
prev
, xem bước tiếp theo) và trường đầu tiên của dòng hiện tại, được phân tách bằng dấu tách trường đầu ra (ký tự khoảng trắng theo mặc định);prev
biến;Phương awk
pháp thay thế :
$ awk 'NR == 1{printf "%s", $0;next}{printf " %s\n%s", $1,$0}' input.txt
abc 123 abc
abc 789 bcd
bcd 456 acb
acb 135
Cách thức hoạt động này rất đơn giản: dòng đầu tiên là trường hợp đặc biệt - chúng tôi in nó mà không có dòng mới và bảo awk đi đến dòng tiếp theo mà không thực hiện các khối mã khác. Sau đó, NR == 1{printf "%s", $0;next}
được bỏ qua, nhưng các phần khác làm công việc.
Hãy nhớ rằng cho đến nay chúng tôi đã in một chuỗi được định dạng mà không có ký tự dòng mới. Do đó, những gì đang được thực hiện printf " %s\n%s",$1,$0
bây giờ là từ đầu tiên được in ra (và vì không có dòng mới, nó vẫn nằm trên cùng một dòng đầu ra), dòng mới được chèn, và sau đó toàn bộ dòng (nhưng không kết thúc bằng ký tự dòng mới) . Do đó, từ đầu tiên tiếp theo được chèn sẽ vẫn nằm trên cùng một dòng. Quá trình tiếp tục và tiếp tục cho đến khi chúng tôi đạt đến cuối tập tin.
Cải tiến có thể là bao gồm END{print ""}
khối để chèn dòng mới cuối cùng. Trong một số trường hợp trong đó tệp kết quả sẽ được xử lý bởi các tập lệnh khác, nó có thể được mong muốn.
Mặc dù người dùng yêu cầu AWK một cách cụ thể, ví dụ, cách tiếp cận tương tự với việc in các chuỗi được định dạng có thể được thực hiện với các ngôn ngữ khác, ví dụ như Python. Python thay thế được cung cấp cho những người tò mò về cách thực hiện điều này bằng các ngôn ngữ khác:
#!/usr/bin/env python
from __future__ import print_function
import sys
old = None
for index,line in enumerate(sys.stdin):
if index == 0:
print(line.strip(),end=" ")
continue
words = line.strip().split()
print(words[0] + "\n" + line.strip(),end=" ")
Và cách sử dụng như vậy:
$ ./append_first.py < input.txt
abc 123 abc
abc 789 bcd
bcd 456 acb
acb 135
Ý tưởng tương tự về dòng mới cuối cùng áp dụng ở đây.
Đây là một sed
cách xấu xí chỉ để cho vui
sed '2,$ s/[^ ]\+/& &/; 2,$ s/ /\n/' file | paste -d ' ' - -
abc 123 abc
abc 789 bcd
bcd 456 acb
acb 135
2,$
từ dòng thứ hai đến dòng cuối cùngs/[^ ]\+/& &/
nhân đôi bộ ký tự không khoảng trắng đầu tiên;
tách các lệnh, như trong shells/ /\n/
thay thế không gian đầu tiên bằng một dòng mớipaste -d ' ' - -
dính mớ hỗn độn này lại với nhau (nối dòng thứ hai vào dòng thứ ba, dòng thứ tư với dòng thứ ba, v.v.)sed
chương trình cho vui, thì có lẽ bạn nên chơi code-golf ;-)
Theo tôi cách tiếp cận đơn giản và dễ đọc nhất là:
cut
)tail
)paste
)Ví dụ: tệp inpult mẫu của bạn:
abc 123
abc 789
bcd 456
acb 135
Sau đó chạy lệnh sau trong một thiết bị đầu cuối
cut -d' ' -f1 in.txt | tail -n +2 | paste -d' ' file -
Đầu ra:
abc 123 abc
abc 789 bcd
bcd 456 acb
acb 135
Cấu trúc đằng sau giải pháp này khác với các câu trả lời đã cho. Không cần điều kiện, vòng lặp hoặc biểu thức chính quy.
sed
tự mình sử dụng mà không cầnpaste
:sed -r 'N;s/\n(\w+)/\1&/;P;D' somefile.txt