apt-get remove với wildcard loại bỏ cách hơn dự kiến. tại sao?


38

Đêm qua tôi đã cố gắng ghi đĩa CD. Vì khó chịu với k3b và chọn sử dụng brasero thay vào đó, tôi đã đi gỡ bỏ k3b.

Tôi gõ vào:

sudo apt-get remove k3b

Tôi nhấn tab hai lần và thấy rằng tôi có cả dữ liệu k3b và k3b trên hệ thống của mình. Giả sử rằng tôi sẽ không cần dữ liệu k3b trên hệ thống của mình mà không có k3b, tôi cũng muốn xóa nó vì vậy tôi đã nhập:

sudo apt-get remove k3b*

Thật không may, tôi nhấn Y để xác nhận mà không cần nhìn. Nó gỡ cài đặt rất nhiều hơn k3bk3b-data. Nó gỡ cài đặt các gói không phù hợp với k3b*regex của tôi . Ví dụ: transmissionnetwork-manager.

Tôi khá chắc chắn rằng tôi không có khoảng trống giữa k3b*nhưng tôi không biết tại sao nó lại xóa tất cả những gì nó đã làm. Có điều gì đó về apt-get mà tôi đang hiểu lầm?


Câu trả lời:


38

Lệnh bạn muốn là sudo apt-get remove '^k3b.*', bởi vì:

  • Bạn cần .*phải phù hợp với bất kỳ nhân vật, số lần
  • Bạn cần ^khớp với phần bắt đầu của chuỗi
  • Bạn cần trích dẫn regex để ngăn bash diễn giải *thành ký tự đại diện

(Câu trả lời này hoàn thành và tóm tắt thông tin trước đó được cung cấp bởi qbi và Flimm)


5
Điều này là an toàn và sử dụng nó là ổn nhưng bạn không cần .*. Bạn chỉ có thể sử dụng sudo apt-get remove ^k3b. Sự hiện diện của ^là đủ để làm cho đối số được hiểu là một biểu thức chính quy và khi apthoặc apt-getdiễn giải một đối số là một biểu thức chính quy, nó khớp với bất kỳ vị trí nào trong tên gói. Đó là lý do tại sao bạn cần - ^để neo trận đấu vào đầu tên gói. Biểu thức chính quy không cần khớp với toàn bộ tên gói, chỉ là bất kỳ phần nào của nó.
Eliah Kagan

1
@EliahKagan Thx để biết thêm thông tin! (và thực tế, nó có ý nghĩa rằng nếu bạn cần ^, thì bạn không cần .*)
Boris Dalstein

30

Biểu thức chính quy *là số không hoặc nhiều tùy ý. Vì vậy, bạn đã yêu apt-getcầu loại bỏ bất cứ thứ gì có chứa k3theo sau bởi bất kỳ số lượng nào b, vì vậy về cơ bản mọi thứ có chứa k3. Nếu tôi thử lệnh của bạn trên hệ thống của tôi, nó muốn xóa 58 gói.

sudo apt-get remove -s k3b*
Package k3b is not installed, so not removed
Package k3b-data is not installed, so not removed
Package k3b-dbg is not installed, so not removed
Package libcanberra-gtk3-0 is not installed, so not removed
Package libcanberra-gtk3-0-dbg is not installed, so not removed
Package libcanberra-gtk3-dev is not installed, so not removed
…
The following packages will be REMOVED:
  appmenu-gtk ardour audacity brasero brasero-cdrkit firefox-globalmenu
  gconf-editor gir1.2-appindicator-0.1 gnome-applets gnome-control-center
…
0 upgraded, 2 newly installed, 58 to remove and 0 not upgraded.

ừ! Tôi đã bị mắc kẹt khi làm việc trên các máy cửa sổ chết tiệt này (trong đó * chỉ có nghĩa là "và bất cứ điều gì sau") quá lâu!
Steve Goykovich

14
*hoạt động như một ký tự đại diện cho bash như trong DOS, nhưng một số lệnh như apt-getmong đợi một regex. Khi bạn nhập sudo apt-get remove -s k3b*, bash trước tiên sẽ tìm bất kỳ tệp nào trong thư mục hiện tại của bạn bắt đầu bằng k3b. Nếu nó tìm thấy bất kỳ, nó sẽ thay thế đối số đó bằng các tên tệp đó. Nếu không, nó sẽ chuyển k3b*trực tiếp đến apt-get, nó sẽ diễn giải nó như một biểu thức chính quy. Nếu trước tiên bạn không muốn bash diễn giải dấu hoa thị thành ký tự đại diện (mà bạn có thể không biết), hãy bao quanh đối số bằng các trích dẫn đơn, như thế này:sudo apt-get remove -s 'k3b*'
Flimm

3
Vì vậy, lệnh dự định sẽ có được sudo apt-get remove -s 'k3b.*'. Chỉ cần vấp phải câu trả lời này và thấy nó thực sự quan trọng để biết. IMHO điều này khá bất ngờ và tôi hoàn toàn đánh dấu nó là một lỗi "hành vi bất ngờ" của apt-get ... bạn thường mong đợi một ý nghĩa "toàn cầu" chứ không phải là "regrec" nếu không được chỉ định. Dù sao cũng cảm ơn và +1!
Rmano

1
Và đối với những người như tôi không biết: -stùy chọn này có nghĩa là "mô phỏng". Nó nói apt-getkhông thực hiện thao tác, mà chỉ đơn giản là thông báo cho bạn về những gì sẽ xảy ra mà không có -stùy chọn.
Boris Dalstein

Tôi nghĩ rằng việc bạn sử dụng các trích dẫn đơn lẻ để tạo ra toàn cầu KHÔNG hoạt động, ít nhất là trong múa rối. Và đó điều bất ngờ. Trong chương trình 'find', nếu tôi viết find / -iname 'project *' tôi sẽ tìm thấy mọi thứ bắt đầu với dự án, không phải thứ gì đó có 'dự án' trong đó và bất cứ thứ gì sau nó. Bằng chứng liên quan đến con rối, hãy chú ý kết quả của tôi nói 'regex' và kết quả chứng minh điều đó như thế nào?
Dennis

9

Sử dụng sudo apt-get remove ^k3bthay thế. Khi bạn cài đặt hoặc gỡ bỏ các gói, *thường nguy hiểm và hiếm khi cần thiết. Nếu bạn sử dụng *, bạn nên trích dẫn nó, nhưng điều đó không làm cho nó an toàn hơn, bởi vì xu hướng chọn nhiều gói hơn bạn dự định là kết quả của cách thức aptapt-getdiễn giải nó chứ không phải là hiệu ứng của việc mở rộng tên đường dẫn .

  • Thậm chí sử dụng an toàn*thường không cần thiết .
  • Sử dụng không an toàn là tàn bạo . Xóa k3b*bỏ loại bỏ mọi gói có chứa k3 bất cứ nơi nào trong tên của nó (và mọi gói phụ thuộc vào gói đó). Đó không phải là một lỗi đánh máy - chứa k3là đủ, thậm chí không có b, bởi vì b*có nghĩa là "không hoặc nhiều hơn bs."

Khi bạn chạy apthoặc apt-getvới install, removehoặc purgehành động, mỗi đối số tiếp theo là lần đầu tiên 1 hiểu là tên của một gói cá nhân. Nếu một gói có tên chính xác đó tồn tại, hành động được thực hiện cho nó.

Nếu không có gói như vậy, aptapt-getsẽ kiểm tra nếu đối số có chứa bất kỳ trong những phổ biến biểu thức chính quy metacharacters 2 . , ?, +,* , |, \[, ^, hoặc$ . Nếu không, nó đã được thực hiện - không có gói nào được tìm thấy.

Nếu nó chứa bất kỳ ký tự nào trong số đó, thì nó được coi là một biểu thức chính quy và khớp với bất kỳ phần nào của bất kỳ tên gói nào. Nó không phải phù hợp với toàn bộ tên. Như những người khác đã nói, *trong một biểu thức chính quy không có nghĩa tương tự như *trong một quả địa cầu. ?cũng không. Trong một biểu thức chính quy:

  • *cho phép mục trước xuất hiện bất kỳ số lần nào - chỉ bao gồm một lần hoặc không hoàn toàn - thay vì chính xác một lần.
  • ?làm cho mục trước đó là tùy chọn - đó là, nó cho phép nó xuất hiện 0 hoặc một lần.

apt-get (8) ( man apt-get) nói:

Nếu không có gói nào khớp với biểu thức đã cho và biểu thức chứa một trong số '.', '?' hoặc '*' thì nó được coi là biểu thức chính quy POSIX và được áp dụng cho tất cả các tên gói trong cơ sở dữ liệu. Bất kỳ trận đấu sau đó được cài đặt (hoặc loại bỏ). Lưu ý rằng việc khớp được thực hiện bởi chuỗi con nên 'lo. *' Khớp 'how-lo' và 'low'. Nếu điều này là không mong muốn, hãy neo biểu thức chính quy bằng ký tự '^' hoặc '$' hoặc tạo biểu thức chính quy cụ thể hơn.

Manpage chỉ đề cập đến ., ?*, nhưng nó là không đầy đủ , như +, |, [, ^, và $cũng đủ để cho apt-gethoặc aptgiải thích các mô hình như một biểu thức chính quy. 3

Mặc dù bạn có thể khớp bất kỳ số lượng bất kỳ ký tự nào với .*- không chỉ - bạn *chỉ cần điều này nếu nó xuất hiện ở giữa biểu thức thông thường của bạn. Vì mẫu được khớp với bất kỳ chuỗi con nào của tên gói, nên nó vô nghĩa ở cuối (hoặc bắt đầu) của mẫu.

Các trang web đề cập ^$ . Những (đặc biệt ^) là chìa khóa để viết an toàn, mô hình hiệu quả để sử dụng với install, removehoặc purgehành động trong apthoặc apt-get.

  • ^neo một biểu thức chính quy vào đầu của toàn bộ chuỗi. ^k3bchọn tất cả các gói có tên bắt đầu bằng k3b.
  • $neo một biểu thức chính quy vào cuối của toàn bộ chuỗi. k3b$sẽ chọn tất cả các gói có tên kết thúc bằng k3b.

Do đó, bạn có thể sử dụng lệnh này để gỡ bỏ các gói một cách an toàn:

sudo apt-get remove ^k3b

Cuối cùng, trong trường hợp cụ thể mà bạn đã đề cập, bạn cũng có thể tự mình vượt qua cả hai tên:

sudo apt-get remove k3b k3b-data

Sau đó, bạn tránh tất cả sự phức tạp này! (Mặc dù việc neo với ^đơn giản là một khi bạn đã quen với nó.) Hoặc sử dụng mở rộng dấu ngoặc , mà vỏ của bạn mở rộng thành lệnh trên:

sudo apt-get remove k3b{,-data}

1 Có hai trường hợp ngoại lệ như sau: (a) một số tùy chọn (ví dụ -f, --purge) được công nhận, và (b) một số ký tự dấu xuất hiện tại cuối của một cuộc tranh cãi rằng nếu không sẽ được thực hiện như là một tên gói để thực hiện các hành động có thể được sử dụng để thay đổi những gì được thực hiện (ví dụ: sudo apt install ubuntu-desktop^cài đặt tác vụ thay vì gói và khi ^xuất hiện ở cuối).

2 Siêu ký tự biểu thức chính quy khác tồn tại. Ví dụ, \được hỗ trợ bởi tất cả các phương ngữ của biểu thức chính quy và thường được sử dụng. ., ?, +, *, |, [, ^, Và $chỉ xảy ra là metacharacters các nhà phát triển APT quyết định sẽ kích hoạt sự giải thích như một biểu thức chính quy (sau độ phân giải như một gói chính xác tên đã thất bại).

3 Cách dễ nhất để xác minh điều này là mô phỏng cài đặt hoặc gỡ bỏ với một mẫu như vậy, sử dụng -stùy chọn như mô tả ở trên. Ví dụ, việc chạy các apt -s install ^virtualboxchương trình sudo apt install ^virtualboxsẽ có tác dụng cố gắng cài đặt mọi gói mà người quản lý gói biết về tên bắt đầu bằng virtualbox. Tuy nhiên, hành vi này cũng có thể được xác minh bằng cách kiểm tra mã nguồn . Kiểm tra CacheSetHelper::PackageFromRegExchức năng trong cacheset.cc.


1

Sau đó, bạn có khả năng loại bỏ một lib có k3b trong đó các chương trình đó phụ thuộc vào.

Tóm lại bạn có thể không bao giờ biết. Tôi khuyên bạn không nên sử dụng ký tự đại diện để xóa mọi thứ và đọc mọi thứ khi được nhắc (xin lỗi).

Ngoài ra, các tìm kiếm regex -n sử dụng tất cả các trường và không chỉ tên

http://ccrma.stanford.edu/planetccrma/man/man8/apt-cache.8.html

Ngoài ra qbi là chính xác regex của bạn bị lỗi từ get-go


Một điều khác, trong các trường hợp như của bạn (dữ liệu k3b và k3b) chỉ cần gỡ cài đặt apt-get k3b. Sau đó, Apt sẽ thông báo cho bạn nếu bạn đã cài đặt những thứ mà bạn không còn cần nữa và những gì bạn cần làm để loại bỏ chúng.
coteyr

ồ Tôi sẽ không bao giờ mong đợi nó sẽ tìm kiếm trong các mô tả quá! Vâng, đây chắc chắn là điều tôi sẽ không bao giờ làm lại! (và tôi chắc chắn sẽ đọc những thứ vào lần tới: P)
Steve Goykovich

Liên kết bị hỏng, bạn có phiền khi làm rõ cách sử dụng -n không?
Seanny123

-n có nghĩa là chỉ tìm kiếm trong trường tên.
coteyr

Sau khi thử, tùy chọn -n không được nhận ra bởi apt-get remove, chỉ bởi apt-get cache. Có vẻ như thực sự, apt-get removechỉ tìm tên gói, không phải mô tả.
Boris Dalstein
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.