Bagaimana cara mendapatkan kata pertama dari sebuah string?


43

Ketika saya 'echo *' mendapatkan output berikut:

file1 file2 file3 ...

Yang saya inginkan adalah memilih kata pertama. Bagaimana saya bisa melanjutkan?


1
@mattdm Menggunakan lstidak akan berfungsi jika salah satu nama file berisi kosong.
helpermethodhod

2
Bagaimana Anda mendefinisikan kata ? Jika file pertama adalah Sunset on a beach.jpg, haruskah itu Sunsetseluruh nama file? Bagaimana dengan Sea, sex and sun.ogg? Sea, Sea,atau seluruh nama file?
Stéphane Chazelas

@mattdm ls | head -1memberi saya hal-hal acak seperti a.patch p.pyyang bukan kata pertama dan bahkan file dalam urutan abjad.
phuclv

Jawaban:


52

Anda dapat menyalurkannya melalui awk dan membuatnya menggemakan kata pertama

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

atau Anda memotong string dan memilih kata pertama:

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

atau Anda pipa itu sed sedor dan menghapus semuanya kecuali kata pertama

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

Menambahkan | head -n1untuk memuaskan nitpickers. Jika string Anda berisi baris baru | head -n1akan memilih baris pertama terlebih dahulu sebelum perintah penting pilih kata pertama dari string yang diteruskan ke sana.


1
Itu akan mengembalikan kata pertama dari setiap baris, bukan kata pertama.
Stéphane Chazelas

2
saya bertanya-tanya berapa banyak baris yang echo *dihasilkan
Bananguin

Itu tergantung berapa banyak file yang memiliki karakter baris baru dalam namanya atau tergantung pada lingkungan atau bagaimana bash dikompilasi atau apakah beberapa file dipanggil -eatau -ee... muncul dalam daftar, berapa kali \nmuncul dalam nama file. Jika ada file yang dipanggil -n, itu mungkin bahkan tidak mengembalikan baris sama sekali ...
Stéphane Chazelas

Yah, kita masih berbicara bash dan 1. biasanya bash tidak akan melewatkan string dengan baris baru sebagai satu string dengan baris baru 2. Sangat sulit dan tidak biasa (tidak mungkin?) Untuk memiliki baris baru dalam nama file 3. a \ n di nama file akan muncul sebagai \ n 4. 3 berlaku untuk nama file yang dimulai dengan - 5. bahkan ketika dipanggil dengan -n atau -e echo akan membuka stdout dan menutupnya ketika selesai maka tentu saja ia akan mengembalikan garis, dan pada setidaknya satu string, dalam hal ini 6. saya mengedit saran saya untuk setidaknya menangani masalah multiline
Bananguin

1
Semua 5 poin itu salah. Coba di dir kosong: touch '$a\nb' 'a\nb'; env BASHOPTS=xpg_echo bash -c 'echo * | wc -l'( xpg_echodiaktifkan di mana pun bashdiperlukan untuk menjadi Unix sesuai). Dan dalam direktori kosong lain: touch ./-n; bash -c 'echo * | wc -l'. Baris adalah urutan karakter yang diakhiri oleh karakter baris baru. Jika echotidak menampilkan karakter baris baru, itu tidak menghasilkan garis apa pun. Perilaku utilitas teks suka cut, awkatau sedtidak ditentukan jika input memiliki karakter tambahan setelah karakter baris baru terakhir dan perilaku bervariasi di seluruh implementasi.
Stéphane Chazelas

18

Dengan asumsi shell posixy ( /bin/shatau /bin/bashdapat melakukan ini)

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

Konstruksinya ${all%% *}adalah contoh penghapusan substring . The %%berarti menghapus pertandingan terpanjang *(ruang diikuti oleh apa pun) dari ujung kanan dari variabel all. Anda dapat membaca lebih lanjut tentang manipulasi string di sini .

Solusi ini mengasumsikan bahwa pemisah adalah ruang. Jika Anda melakukan ini dengan nama file maka setiap spasi akan memecahnya.


Bagus Tapi saya suka versi sederhana dan lebih non-hacky dengan headdancut
Anwar

4
IMO, head, cut & sed kurang sederhana. Mengapa menelurkan alat lain ketika subtitusi parameter bawaan melakukan pekerjaan dengan efisien. Jawaban ini adalah yang paling efisien dan cara yang paling portabel untuk memilih kata pertama dari daftar kata-kata yang dipisahkan oleh ruang (yang semuanya diminta oleh OP).
Juan

7

Dengan asumsi bahwa Anda benar-benar menginginkan nama file pertama dan bukan kata pertama , inilah cara yang tidak pecah di spasi putih:

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

1
Kata pertama juga akan mudah:files=($(echo *))
Hauke ​​Laging

2
Akan pecah pada "-n", "-e", "-ne", "-Enenene" ..., dan tergantung pada bagaimana bashdikompilasi atau lingkungan, mungkin pada karakter backslash.
Stéphane Chazelas

2
@ HaukeLaging, Anda harus menonaktifkan globbing. Seperti text=$(echo *); set -f; files=($text):, jika tidak, lebih banyak wildcard dapat diperluas.
Stéphane Chazelas

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

1
@memnoch_proxy Ini akan merusak nama file yang mengandung spasi, gunakan dengan hati-hati.
Chris Down

5

Anda dapat menggunakan parameter posisi

set -- *
echo "$1"

3
Ketahuilah bahwa ini akan memusnahkan argumen lain pada skrip Anda, kecuali dijalankan dalam lingkup bantu. Ini juga akan diperluas ke *jika tidak ada file di direktori.
Chris Down

shopt -s nullglobakan menangani itu
glenn jackman

3

Periksa salah satu alternatif berikut:

$ FILE=($(echo *))
$ FILE=$(echo * | grep -o "^\S*")
$ FILE=$(echo * | grep -o "[^ ]*")
$ FILE=$(find . -type f -print -quit)

Kemudian Anda dapat mencetaknya melalui echo $FILE.

Lihat juga: grepsatu-satunya kata pertama dari keluaran?



1

Mendapatkan seluruh nama file pertama:

shopt -s nullglob
printf '%s\000' * | grep -z -m 1 '^..*$'
printf '%s\000' * | ( IFS="" read -r -d "" var; printf '%s\n' "$var" )
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.