Lấy các ký tự [x] đầu tiên cho một chuỗi từ một đường ống


Câu trả lời:


82

Một cách là sử dụng cut:

 command | cut -c1-8

Điều này sẽ cung cấp cho bạn 8 ký tự đầu tiên của mỗi dòng đầu ra. Vì cutlà một phần của POSIX, nên có khả năng nó sẽ có mặt trên hầu hết các Thông báo.


3
Lưu ý rằng cut -cchọn ký tự; cut -bhoặc head -cchọn byte. Điều này tạo ra sự khác biệt ở một số địa phương (trong thực tế, khi sử dụng UTF-8).
Gilles 'SO- ngừng trở thành ác quỷ'

Bạn cũng không phải chỉ định chỉ số bắt đầu trong trường hợp này. Saying cut -c-8sẽ chọn từ ký tự 1 đến 8.
Sparhawk

@Steven, cuttương đương trên Windows là?
Pacerier

Ngoài ra command | dd bs=8 count=1 2>/dev/null. Không nói nó ngắn hơn hay vượt trội. Chỉ là một sự thay thế khác.
dubiousjim

@Gilles, nhưng lưu ý rằng với các phiên bản hiện tại của GNU cut, cut -choạt động như thế cut -b(nghĩa là, nó không hoạt động chính xác cho các ký tự nhiều byte).
Stéphane Chazelas

24

Đây là một số cách khác để chỉ có 8 ký tự đầu tiên.

command | head -c8

command | awk '{print substr($0,1,8);exit}' 

command | sed 's/^\(........\).*/\1/;q'

Và nếu bạn có bash

var=$(command)
echo ${var:0:8}

2
Tôi nghĩ rằng công thức sed sau đây dễ đọc hơn một chút: command | sed 's/\(.\{8\}\).*/\1/'hoặc nếu sed của bạn hỗ trợ nó : command | sed -r 's/(.{8}).*/\1/'; Mặt khác, +1
Steven D

Thứ tốt, nhưng lưu ý rằng head -cđếm byte , không phải ký tự. Tương tự, trong số các triển khai Awk chính, chỉ GNU awk xử lý chính xác các ký tự nhiều byte - FreeBSD Awk và Mawk thì không.
mkuity0

2

Nếu bạn có trình bao đủ nâng cao (ví dụ: phần sau sẽ hoạt động trong Bash, không chắc chắn về dấu gạch ngang), bạn có thể làm:

read -n8 -d$'\0' -r <(command)

Sau khi thực hiện read ... <(command), các ký tự của bạn sẽ ở trong biến shell REPLY. Nhập help readđể tìm hiểu về các tùy chọn khác.

Giải thích: -n8đối số để readnói rằng chúng tôi muốn tối đa 8 ký tự. Các -d$'\0'nói đọc cho đến khi một null, chứ không phải là một dòng mới. Bằng cách này, việc đọc sẽ tiếp tục cho 8 ký tự ngay cả khi một trong các ký tự trước đó là một dòng mới (nhưng không phải là một ký tự không). Một cách khác -n8 -d$'\0'là sử dụng -N8, đọc chính xác 8 ký tự hoặc cho đến khi stdin đạt EOF. Không có dấu phân cách được vinh danh. Điều đó có thể phù hợp với nhu cầu của bạn hơn, nhưng tôi không biết có bao nhiêu vỏ sò có một lần đọc tôn vinh -Ntrái ngược với tôn vinh -n-d. Tiếp tục với lời giải thích: -rnói bỏ qua \-escapes, do đó, ví dụ, chúng tôi coi \\là hai ký tự, thay vì là một ký tự \.

Cuối cùng, chúng tôi làm read ... <(command)chứ không phải command | read ...vì ở dạng thứ hai, việc đọc được thực thi trong một lớp con sau đó được thoát ngay lập tức, làm mất thông tin bạn vừa đọc.

Một tùy chọn khác là thực hiện tất cả quá trình xử lý của bạn bên trong lớp con. Ví dụ:

$ echo abcdefghijklm | { read -n8 -d$'\0' -r; printf "REPLY=<%s>\n" "$REPLY"; }
REPLY=<abcdefgh>

1
Nếu bạn chỉ muốn xuất 8 ký tự và không cần xử lý chúng trong trình bao, thì chỉ cần sử dụng cut.
dubiousjim

Tốt để biết về read -n <num>; cảnh báo nhỏ: Bash 3.x (vẫn còn trên hệ điều hành) hiểu nhầm <num>là số byte và do đó không thành công với các ký tự nhiều byte; điều này đã được sửa trong Bash 4.x.
mkuity0

Đây là một câu trả lời tuyệt vời và hữu ích. Tổng quát hơn nhiều so với những người khác.
not2qubit

2

Một giải pháp lót khác bằng cách sử dụng mở rộng tham số

echo ${word:0:x}

EG: word="Hello world"
echo ${word:0:3} or echo ${word::3} 
o/p: Hel


EG.2: word="Hello world"
echo ${word:1:3}
o/p: ell

Bạn cũng có thể sử dụng một biến giữ độ dài, ví dụ: x=8; echo ${word:0:$x}thay vì mã hóa số nguyên.
Cometsong

1

Đây là di động:

a="$(command)"             # Get the output of the command.
b="????"                   # as many ? as characters are needed.
echo ${a%"${a#${b}}"}      # select that many chars from $a

Để xây dựng một chuỗi các ký tự có độ dài thay đổi có câu hỏi riêng của nó ở đây .


0

Tôi gặp vấn đề này khi tự tạo các tệp tổng kiểm tra trong kho lưu trữ maven. Thật không may, cut -cluôn luôn in ra một dòng mới ở cuối đầu ra. Để ngăn chặn mà tôi sử dụng xxd:

command | xxd -l$BYTES | xxd -r

Nó xuất ra chính xác $BYTESbyte, trừ khi commandđầu ra của nó ngắn hơn, thì chính xác là đầu ra đó.


một phương pháp khác để gỡ bỏ cutdòng mới của trailing là đưa nó vào:| tr -d '\n'
Cometsong
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.