Làm thế nào để có được từ đầu tiên của một chuỗi?


43

Khi tôi 'echo *' nhận được đầu ra sau:

file1 file2 file3 ...

Điều tôi muốn là chọn ra từ đầu tiên. Làm thế nào tôi có thể tiến hành?


1
@mattdm Sử dụng lssẽ không hoạt động nếu một trong các tên tệp chứa trống.
helpermethod

2
Làm thế nào để bạn xác định từ ? Nếu tập tin đầu tiên là Sunset on a beach.jpg, nó phải là Sunsethoặc toàn bộ tên tập tin? Thế còn Sea, sex and sun.ogg? Sea, Sea,Hoặc tên tập tin toàn bộ?
Stéphane Chazelas

@mattdm ls | head -1mang đến cho tôi những thứ ngẫu nhiên như a.patch p.pykhông phải là từ đầu tiên và thậm chí không phải là tệp theo thứ tự bảng chữ cái.
phuclv

Câu trả lời:


52

Bạn có thể dẫn nó qua awk và làm cho nó lặp lại từ đầu tiên

echo * | head -n1 | awk '{print $1;}'

hoặc bạn cắt chuỗi lên và chọn từ đầu tiên:

echo *  | head -n1 | cut -d " " -f1

hoặc bạn tẩu nó thorugh sed và yêu cầu nó loại bỏ mọi thứ trừ từ đầu tiên

echo * | head -n1 | sed -e 's/\s.*$//'

Đã thêm vào | head -n1để đáp ứng nitopperers. Trong trường hợp chuỗi của bạn chứa dòng mới | head -n1sẽ chọn dòng đầu tiên trước khi các lệnh quan trọng chọn từ đầu tiên từ chuỗi được truyền cho nó.


1
Sẽ trả lại từ đầu tiên của mỗi dòng, không phải từ đầu tiên.
Stéphane Chazelas

2
tôi tự hỏi có bao nhiêu dòng echo *tạo ra
Bananguin

Điều đó phụ thuộc vào số lượng tệp có ký tự dòng mới trong tên của chúng hoặc tùy thuộc vào môi trường hoặc cách bash được biên dịch hoặc liệu một số tệp được gọi -ehoặc -ee... xuất hiện trong danh sách, bao nhiêu lần \nxuất hiện trong tên tệp. Nếu có một tệp được gọi -n, nó thậm chí có thể không trả về bất kỳ dòng nào ...
Stéphane Chazelas

Chà, chúng ta vẫn đang nói bash và 1. thông thường bash sẽ không chuyển một chuỗi có dòng mới thành một chuỗi với dòng mới 2. Rất khó và không bình thường (không thể?) Để có một dòng mới trong tên tệp 3. a \ n in một tên tệp sẽ hiển thị dưới dạng \ n 4. 3 giữ cho tên tệp bắt đầu bằng - 5. ngay cả khi được gọi với -n hoặc -e echo sẽ mở thiết bị xuất chuẩn và đóng nó khi hoàn thành, vì vậy tất nhiên nó sẽ trả về một dòng và tại ít nhất một chuỗi, cho vấn đề đó 6. tôi đã chỉnh sửa lời khuyên của mình để ít nhất quan tâm đến vấn đề đa dòng
Bananguin

1
Cả 5 điểm đều sai. Hãy thử trong một thư mục trống: touch '$a\nb' 'a\nb'; env BASHOPTS=xpg_echo bash -c 'echo * | wc -l'( xpg_echođược bật bất cứ nơi nào bashđược yêu cầu phải tuân thủ Unix). Và trong một thư mục trống khác : touch ./-n; bash -c 'echo * | wc -l'. Một dòng là một chuỗi các ký tự được chấm dứt bởi một ký tự dòng mới. Nếu echokhông xuất ký tự dòng mới, nó không xuất bất kỳ dòng nào. Hành vi của các tiện ích văn bản như cut, awkhoặc sedkhông được chỉ định nếu đầu vào có thêm ký tự sau ký tự và hành vi dòng mới nhất thay đổi trong các lần triển khai.
Stéphane Chazelas

18

Giả sử một vỏ posixy ( /bin/shhoặc /bin/bashcó thể làm điều này)

all=$(echo *)
first=${all%% *}

Cấu trúc ${all%% *}này là một ví dụ về loại bỏ chuỗi con . Có %%nghĩa là xóa kết quả khớp dài nhất của *(một khoảng trắng theo sau bởi bất kỳ thứ gì) từ đầu bên phải của biến all. Bạn có thể đọc thêm về thao tác chuỗi ở đây .

Giải pháp này giả định rằng dải phân cách là một khoảng trắng. Nếu bạn đang làm điều này với tên tệp thì bất kỳ dấu cách nào cũng sẽ phá vỡ nó.


Đẹp một. Nhưng tôi thích phiên bản khác đơn giản và không hack hơn headcut
Anwar

4
IMO, đầu, cắt và sed là ít đơn giản. Tại sao sinh ra một công cụ khác khi thay thế tham số dựng sẵn thực hiện công việc một cách hiệu quả. Câu trả lời này là cách hiệu quả nhất và dễ mang theo nhất để chọn từ đầu tiên của danh sách các từ được phân tách bằng dấu cách (đó là tất cả những gì OP yêu cầu).
Juan

7

Giả sử rằng bạn thực sự muốn tên tệp đầu tiên chứ không phải từ đầu tiên , đây là cách không phá vỡ khoảng trắng:

shopt -s nullglob
files=(*)
printf '%s\n' "${files[0]}"

1
Từ đầu tiên cũng sẽ dễ dàng:files=($(echo *))
Hauke ​​Laging

2
Nó sẽ phá vỡ "-n", "-e", "-ne", "-Enenene" ..., và tùy thuộc vào cách bashbiên dịch hoặc môi trường, có thể là các ký tự dấu gạch chéo ngược.
Stéphane Chazelas

2
@HaukeLaging, bạn cần phải vô hiệu hóa toàn cầu. Giống như : text=$(echo *); set -f; files=($text), nếu không thì nhiều ký tự đại diện có thể được mở rộng.
Stéphane Chazelas

3
files=$(echo *); echo ${files%% *}
vdegenne

1
@memnoch_proxy Nó sẽ phá vỡ tên tập tin có chứa khoảng trắng, sử dụng cẩn thận.
Chris Xuống

5

Bạn có thể sử dụng các tham số vị trí

set -- *
echo "$1"

3
Xin lưu ý rằng điều này sẽ phá hủy mọi đối số khác cho tập lệnh của bạn, trừ khi chạy trong phạm vi phụ trợ. Nó cũng sẽ mở rộng *nếu không có tệp trong thư mục.
Chris Down

shopt -s nullglobsẽ xử lý việc đó
glenn jackman



1

Lấy toàn bộ tên tệp đầu tiên:

shopt -s nullglob
printf '%s\000' * | grep -z -m 1 '^..*$'
printf '%s\000' * | ( IFS="" read -r -d "" var; printf '%s\n' "$var" )
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.