Ở phần đầu của tập lệnh bash shell là dòng sau:
IFS=$'\n'
Ý nghĩa đằng sau bộ sưu tập các biểu tượng này là gì?
IFS=$'\n'
là một bashism (+ shell khác, sử dụng Báo giá ANSI-C , để giải quyết, hãy xem stackoverflow.com/questions/10748703/ trên
Ở phần đầu của tập lệnh bash shell là dòng sau:
IFS=$'\n'
Ý nghĩa đằng sau bộ sưu tập các biểu tượng này là gì?
IFS=$'\n'
là một bashism (+ shell khác, sử dụng Báo giá ANSI-C , để giải quyết, hãy xem stackoverflow.com/questions/10748703/ trên
Câu trả lời:
IFS
là viết tắt của "phân cách trường nội bộ". Nó được sử dụng bởi shell để xác định cách thực hiện phân tách từ, tức là cách nhận biết ranh giới từ.
Hãy thử điều này trong một shell như bash (các shell khác có thể xử lý việc này khác nhau, ví dụ zsh):
mystring="foo:bar baz rab"
for word in $mystring; do
echo "Word: $word"
done
Giá trị mặc định cho IFS
bao gồm các ký tự khoảng trắng (chính xác là: khoảng trắng, tab và dòng mới). Mỗi nhân vật có thể là một ranh giới từ. Vì vậy, với giá trị mặc định là IFS
, vòng lặp ở trên sẽ in:
Word: foo:bar
Word: baz
Word: rab
Nói cách khác, shell nghĩ rằng khoảng trắng là một ranh giới từ.
Bây giờ, hãy thử thiết lập IFS=:
trước khi thực hiện vòng lặp. Lần này, kết quả là:
Word: foo
Word: bar baz rab
Bây giờ, vỏ cũng phân tách mystring
thành các từ - nhưng bây giờ, nó chỉ coi một dấu hai chấm là ranh giới từ.
Ký tự đầu tiên IFS
là đặc biệt: Nó được sử dụng để phân định các từ trong đầu ra khi sử dụng $*
biến đặc biệt (ví dụ được lấy từ Hướng dẫn tập lệnh Bash nâng cao , nơi bạn cũng có thể tìm thêm thông tin về các biến đặc biệt như biến đó):
$ bash -c 'set w x y z; IFS=":-;"; echo "$*"'
w:x:y:z
So với:
$ bash -c 'set w x y z; IFS="-:;"; echo "$*"'
w-x-y-z
Lưu ý rằng trong cả hai ví dụ, vỏ vẫn sẽ đối xử với tất cả các nhân vật :
, -
và ;
như ranh giới từ. Điều duy nhất thay đổi là hành vi của $*
.
Một điều quan trọng khác cần biết là cái gọi là "khoảng trắng IFS" được xử lý như thế nào . Về cơ bản, ngay khi IFS
bao gồm các ký tự khoảng trắng, khoảng trắng đầu và cuối được tách khỏi chuỗi được phân tách trước khi xử lý nó và một chuỗi các ký tự khoảng trắng liên tiếp cũng phân định các trường. Tuy nhiên, điều này chỉ áp dụng cho các ký tự khoảng trắng thực sự có trong đó IFS
.
Ví dụ: chúng ta hãy nhìn vào chuỗi "a:b:: c d "
(dấu cách khoảng trắng và hai ký tự khoảng trắng nằm giữa c
và d
).
IFS=:
nó sẽ được chia thành bốn lĩnh vực: "a"
, "b"
, ""
(trống string) và " c d "
(một lần nữa, hai khoảng trống giữa c
và d
). Lưu ý khoảng trắng hàng đầu và dấu trong trường cuối cùng.IFS=' :'
, nó sẽ được chia thành năm lĩnh vực: "a"
, "b"
, ""
(trống string), "c"
và "d"
. Không có khoảng trắng hàng đầu và dấu ở bất cứ đâu.Lưu ý cách nhiều ký tự khoảng trắng liên tiếp phân định hai trường trong ví dụ thứ hai, trong khi nhiều ký tự liên tiếp không có (vì chúng không phải là ký tự khoảng trắng).
Đối với IFS=$'\n'
, đó là một ksh93
cú pháp cũng được hỗ trợ bởi bash
, zsh
, mksh
và FreeBSD sh
(với các biến thể giữa tất cả vỏ). Trích dẫn trang bash:
Các từ có dạng $ 'chuỗi' được xử lý đặc biệt. Từ này mở rộng thành "chuỗi", với các ký tự thoát dấu gạch chéo ngược được thay thế theo quy định của tiêu chuẩn ANSI C.
\n
là chuỗi thoát cho một dòng mới, vì vậy IFS
cuối cùng được đặt thành một ký tự dòng mới.
bash
hướng dẫn về kịch bản, hoặc bất cứ điều gì. Trong chính, thông tin có sẵn tại các liên kết như thế là thiếu theo những cách quan trọng. Dù sao, do đó bỏ lỡ hai điểm quan trọng liên quan đến việc tách vỏ - khoảng trắng toàn cầu và IFS.
unset IFS
làm cho một chiếc vỏ hoạt động rất khác so với IFS=
. Ngoài ra, byte đầu tiên trong IFS cũng đặc biệt "${named_array[*]}"
- nhưng không có vấn đề gì khi việc mở rộng không được trích dẫn ..
$IFS
một trong hai điều chính được thực hiện khi mở rộng một biến không được trích dẫn trong ngữ cảnh danh sách (đó là split
một phần của split+glob
toán tử). Một cái khác là Globing. Khi sử dụng phân tách công việc, bạn thường cần phải phát hành set -f
để vô hiệu hóa glob
phần.
$IFS
cũng được sử dụng bởi read
lệnh dựng sẵn
Bên trong trích dẫn đơn búp bê, một số nhân vật được đánh giá đặc biệt. Ví dụ, \n
được dịch sang dòng mới.
Vì vậy, dòng đặc biệt này gán dòng mới cho IFS biến. Ngược lại, IFS là một biến đặc biệt trong bash: Dấu tách trường bên trong. Như đã man bash
nói, nó
được sử dụng để phân tách từ sau khi mở rộng và để phân chia các dòng thành các từ bằng
read
lệnh dựng sẵn. Giá trị mặc định là<space><tab><newline>
.
dollared single quotes
khác với trích dẫn đơn giản.
Nói ngắn gọn, IFS=$'\n'
gán dòng mới \n
cho biến IFS
.
$'string'
cấu trúc là một cơ chế trích dẫn sử dụng để giải mã ANSI C giống như các chuỗi thoát. Cú pháp này xuất phát từ ksh93
, và là di động để vỏ hiện đại như bash
, zsh
, pdksh
, busybox sh
.
Cú pháp này không được xác định bởi POSIX, nhưng đã được chấp nhận cho vấn đề SUS 7 .
Tôi thích giải thích $IFS
qua ví dụ:
Suppsoe bạn muốn cp hoặc mv hoặc xử lý tệp khác, IFS trống rỗng bởi defualt, Khi các tệp của bạn có meta char hoặc khoảng trắng như:
Linux Administration.pdf
hoặc Free Software Fundation.ogg
, Chắc chắn bạn sẽ có probelm, Bởi vì: Linux xem xét một tách biệt param và Ad quản lý xem xét một param riêng biệt. Vì vậy, bash có built-in variable
, Sau đó, bạn có thể khởi tạo IFS==$(echo -en "\n\b")
, Sau đó bash loại bỏ bất kỳ meta char và khoảng trắng giữa tên tệp, Ví dụ:
#!/bin/bash
SAVEIFS=$IFS
IFS=$(echo -en "\n\b")
mymusicdir=~/test/dd
find $mymusicdir -name "*" -execdir rename 's/ /_/g' "{}" +
IFS=$SAVEIFS