2012-04-23 23 views
13

Có thể xóa một chuỗi cụ thể bằng lệnh tr trong UNIX-Shell không? Ví dụ: Nếu tôi gõ:Xóa một chuỗi cụ thể với tr

tr -d "1." 

và đầu vào là 1.1231, nó sẽ hiển thị 23 như một đầu ra, nhưng tôi muốn nó hiển thị 1231 (thông báo chỉ 1 đầu tiên đã đi). Tôi sẽ làm như thế nào?

Nếu bạn biết giải pháp hoặc cách tốt hơn, vui lòng giải thích cú pháp vì tôi không muốn chỉ sao chép & dán mà còn để tìm hiểu.

Tôi có vấn đề lớn với awk, vì vậy nếu bạn sử dụng điều này, xin vui lòng giải thích nó nhiều hơn.

+7

Câu trả lời trực tiếp là "không"; 'tr' thay thế các ký tự riêng lẻ, chứ không phải các chuỗi. Vì vậy, (a) lệnh của bạn sẽ xóa tất cả các lần xuất hiện của "1" và "." bất cứ nơi nào trong đầu vào; và (b) 'tr' không phải là lệnh đúng cho nhiệm vụ bạn đang hỏi. – tripleee

Trả lời

5

Trong ví dụ của bạn phía trên lệnh cắt sẽ đủ.

Ví dụ: echo '1.1231' | cut -d '.' -f 2 sẽ trả lại 1231.

Để biết thêm thông tin về cắt, chỉ cần nhập man cut.

+0

Cảm ơn bạn! Hoạt động tuyệt vời! – intelinside

3

Bạn cũng có thể sử dụng sed cho các loại hình điều:

$ echo "1.1231" | sed -e "s/1\.//" 
1231 

này chỉ được sử dụng sed để chạy một tìm kiếm biểu hiện thường xuyên và thay thế, thay thế "1." (với thoát thích hợp) với "". Nó chỉ xóa trận đấu đầu tiên theo mặc định.

3

Nếu bạn đang sử dụng bash, bạn có thể làm điều này một cách dễ dàng với parameter substitution:

$ a=1.1231 
$ echo ${a#1.} 
1231 

này sẽ loại bỏ các hàng đầu"1." chuỗi. Nếu bạn muốn xóa tối đa và bao gồm số lần xuất hiện đầu tiên, hãy sử dụng ${a#*1.} và nếu bạn muốn xóa mọi thứ tối đa và bao gồm lần xuất hiện mới nhất, hãy sử dụng ${##*1.}.

Trang TLDP trên string manipulation có các tùy chọn khác (chẳng hạn như trích xuất chuỗi con).

Lưu ý rằng việc sử dụng tiêu chuẩn sh xây dựng các công cụ chuỗi thao tác cho biến đổi đơn giản như vậy sẽ luôn luôn là nhanh hơn nhiều so với sử dụng một công cụ bên ngoài, chẳng hạn như sed, awk hoặc cut vì vỏ không nhất thiết phải tạo ra một tiểu trình để thực hiện thao tác. Tuy nhiên, đối với những thứ phức tạp hơn (ví dụ: bạn cần sử dụng cụm từ thông dụng hoặc khi đầu vào lớn), bạn nên sử dụng các công cụ chuyên dụng hơn.

+0

Đây cũng là một giải pháp tuyệt vời! Cảm ơn. – intelinside

9

Bạn nên sử dụng một số loại regex (có thể giống như sed).

Ví dụ: với đầu vào 1.1231 bạn có thể sử dụng sau đây để có được 1231 sản lượng:

sed 's/1\.//g' 

Có lẽ có một cái nhìn ở đây: http://tldp.org/LDP/abs/html/string-manipulation.html

+0

"Sử dụng tốt 'tr'", tôi đồng ý rằng điều này dễ sử dụng hơn và dễ đọc hơn, cho các biểu thức đơn giản. – ThorSummoner

2

Vì bạn hỏi cụ thể về awk, đây là một số khác.

awk '{ gsub(/1\./,"") }1' input.txt 

Như bất kỳ awk hướng dẫn sẽ cho bạn biết, hình thức chung của một chương trình awk là một chuỗi các 'tình trạng {hành động}'. Nếu bạn không có hành động nào, hành động mặc định sẽ được in. Nếu bạn không có điều kiện, các hành động sẽ được thực hiện vô điều kiện. Chương trình này sử dụng cả hai trường hợp đặc biệt này.

Phần đầu tiên là một hành động không có điều kiện, tức là nó sẽ được thực hiện cho tất cả các dòng. Hành động là thay thế tất cả các lần xuất hiện của cụm từ thông dụng /1\./ mà không có gì. Vì vậy, điều này sẽ cắt bất kỳ '1.' (bất kể ngữ cảnh) từ một dòng.

Phần thứ hai là điều kiện không có hành động, tức là phần này sẽ in nếu điều kiện là đúng và điều kiện luôn đúng. Đây là một thành ngữ phổ biến cho "chúng tôi đã làm - in bất cứ điều gì chúng tôi có bây giờ". Nó bao gồm chỉ đơn giản là hằng số 1 (mà khi được sử dụng như một điều kiện có nghĩa là "true", đơn giản).

Điều này có thể được cải cách theo một số cách. Ví dụ, bạn có thể đưa yếu tố in vào hành động đầu tiên;

awk '{ gsub(/1\./,""); print }' input.txt 

Có thể bạn muốn thay thế phần nguyên, tức là bất kỳ số nào trước dấu chấm. Các regex cho rằng sẽ là một cái gì đó như /[0-9]+\./.

gsub là một phần mở rộng của GNU, vì vậy bạn có thể muốn thay thế bằng sub hoặc một số loại vòng lặp nếu bạn cần tính di động cho cú pháp cũ awk.

Các vấn đề liên quan