awk sed nếu tuyên bố


9

Tôi đang cố gắng thêm 0 vào đầu, NẾU có dấu "." tại ký tự thứ 2 của dòng đó. Tôi không thể kết hợp cả hai;

awk '{ print substr( $0, 2, 1 ) }' file.txt 

thể hiện nhân vật thứ hai

sed -ie "s/.\{0\}/0/" file.txt

thêm một số không vào đầu.

Cần có một "nếu ký tự thứ hai là một dấu chấm".

tập tin mẫu:

1.02.2017 23:40:00
10.02.2017 23:40:00

sau cùng:

01.02.2017 23:40:00
10.02.2017 23:40:00

Câu trả lời:


12

Chúng tôi có thể sử dụng một trong hai sedhoặc awkđể giải quyết hoàn toàn vấn đề.


Với sed:

$ sed 's/^.\./0&/' file.txt

Khi &xảy ra trong phần thay thế của lệnh thay thế ( s), nó sẽ được mở rộng thành một phần của dòng đầu vào khớp với phần mẫu của lệnh.

Biểu thức chính quy ^.\.có nghĩa là " khớp tất cả các dòng bắt đầu bằng ( ^) một ký tự tùy ý ( .) theo sau là một dấu chấm ( \.) ".

Nếu dòng là 1.02.2017 23:40:00, mẫu sẽ khớp và 1.sẽ được thay thế bằng 01.ở đầu dòng.


Với awk:

Dựa trên awkmã một phần trong câu hỏi ...

Điều này sẽ, như đã nêu, in ký tự thứ hai của mỗi dòng đầu vào:

$ awk '{ print substr($0, 2, 1) }' file.txt

Chúng ta có thể sử dụng thực tế substr($0, 2, 1)trả về ký tự thứ hai và sử dụng nó làm điều kiện:

$ awk 'substr($0, 2, 1) == "." { ... }' file.txt

Mã đi vào { ... }là mã bổ sung $0, là nội dung của dòng hiện tại, với số 0 nếu điều kiện trước là đúng:

$ awk 'substr($0, 2, 1) == "." { $0 = "0" $0 }' file.txt

Sau đó, chúng ta chỉ cần đảm bảo rằng tất cả các dòng được in:

$ awk 'substr($0, 2, 1) == "." { $0 = "0" $0 } { print }' file.txt

Điều kiện substr($0, 2, 1) == "."tất nhiên cũng có thể được thay đổi thành biểu thức chính quy (chúng tôi sử dụng chính xác biểu thức giống như chúng tôi đã sử dụng trong sedgiải pháp):

$ awk '/^.\./ { $0 = "0" $0 } { print }' file.txt

Một số người nghĩ rằng "ngắn hơn luôn luôn tốt hơn" sẽ viết như

$ awk '/^.\./ { $0 = "0" $0 } 1' file.txt

(và có lẽ cũng loại bỏ hầu hết các khoảng trắng awk '/^.\./{$0="0"$0}1' file.txt:)


1
+1 Ví dụ AWK cuối cùng của bạn hoặc ví dụ sed của bạn là những cách chính xác để làm điều này. Lưu ý, cho rõ ràng, nó sẽ chỉ là một hoặc khác.
Tạm dừng cho đến khi có thông báo mới.

Theo tôi, cách tiếp cận "chính xác" (không phù hợp với không gian và dù sao trọng lượng nhẹ hơn) là phiên bản cuối cùng của bạn , sed 's/^.\./0&/' file.txt. Tôi nghĩ bạn nên đặt nó ở đầu câu trả lời này. Tuy nhiên, +1.
tự đại diện

1
@Wildcard Chúng tôi mong muốn làm hài lòng.
Kusalananda

5

Với sed:

sed -e "/^.\./s/^/0/" file.txt 

Mẫu /^.\./tìm kiếm bất kỳ ký tự và dấu chấm nào ở đầu dòng ^và nếu phù hợp, shãy tạo ra dòng bắt đầu bằng số 0, thêm số 0 vào đầu một cách hiệu quả.

Sed expressoin s/.\{0\}/0/có phần kỳ quặc, nó khớp với 0 hoặc nhiều bản sao của bất cứ thứ gì và thay thế bằng số không. Mẫu tất nhiên sẽ khớp ở mọi vị trí của chuỗi, nhưng vì s///chỉ thay thế khớp đầu tiên, nên nó hoạt động như bạn dự định. Một cách kỳ lạ để làm điều đó, mặc dù.


Hoặc với awk, một regex tương tự sẽ hoạt động để khớp với dòng, nhưng chúng ta có thể sử dụng substr:

awk 'substr($0, 2, 1) == "." {$0 = "0" $0} 1' file.txt 

Trước tiên, chúng tôi kiểm tra xem ký tự thứ hai có phải là dấu chấm không, sau đó thêm số 0 vào trước dòng nếu có. Cái cuối cùng gọi hành động mặc định của việc in dòng sau bất kỳ sửa đổi nào.


4

Bạn nói awk và sed, nhưng có vẻ như bạn đang cố định dạng một ngày và vì thế tôi sẽ sử dụng datelệnh. Ví dụ:

echo '1.2.2017 23:40:00' | sed 's/\./\//g' | xargs -0 date '+%m.%d.%Y %T' -d

sẽ xuất

01.02.2017 23:40:00

Các sedlệnh ở giữa thay đổi thời gian để dấu gạch chéo để đưa vào date -d. Các tùy chọn định dạng cho phép đầu ra ở hầu hết mọi định dạng bạn muốn. Các %mđặc biệt là ý chí zero-pad tháng, đó là những gì nó có vẻ như bạn đang cố gắng làm.

Như Kusalananda chỉ ra:

Thậm chí gọn hơn (ngày GNU và Bash): date -f <(tr '.' '/' <dates.in) '+%m.%d.%Y %T'


2
Bắt tốt đẹp! Thậm chí gọn hơn (ngày GNU và Bash):date -f <(tr '.' '/' <dates.in) '+%m.%d.%Y %T'
Kusalananda

Bất cứ khi nào tôi có Dấu gạch chéo trong mẫu của mình, nhưng không có Ống : s|\.|/|g. Mặt khác, như đã lưu ý ở trên: Bắt tốt, +1
Alex Stragies

2

Một chiến lược khác với cách trình bày trong các câu trả lời khác: Bạn có thể sử dụng "." làm dải phân cách trường.

awk -F. '$1 < 10 {printf "0"} {print}' /tmp/in.txt

Bạn có thể đánh gôn này để:

awk -F. '$1<10{printf "0"}1' /tmp/in.txt

Đối với sed, có một lệnh ngắn hơn, được trình bày trong một câu trả lời (tuyệt vời) khác.


1
Thay thế: awk -F. '{print ($1<10?0$0:$0)}' file
George Vasiliou

1

Với sed nó có thể

sed 's/^\(.\)\.\(.*\)/0\1.\2/'

Điều này sẽ sử dụng ^để neo vào đầu dòng, sau đó bắt bất kỳ ký tự đơn nào trong một nhóm, theo sau là một chữ ., sau đó là bất cứ thứ gì khác. Nếu chúng tôi khớp với việc chúng tôi in một 0, thì nhóm chụp đầu tiên của chúng tôi (ký tự ở đầu dòng), sau đó là .nhóm chụp thứ hai của chúng tôi (phần còn lại của dòng)


Không cần thiết phải thực hiện bất kỳ thao tác nào. &là bạn của bạn. Xem ví dụ sed của Kusalananda.
Tạm dừng cho đến khi có thông báo mới.

@DennisWilliamson không cần thiết, nhưng đã có những ví dụ khác, điều này cho thấy một tính năng khác sedcó thể hữu ích trong các tình huống khác, không chỉ là vấn đề cụ thể này
Eric Renouf
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.