shell posix: danh sách in các tên biến môi trường (không có giá trị)


11

Theo cách tương thích với posix hoạt động với nhiều triển khai, làm cách nào tôi có thể in danh sách biến môi trường được xác định hiện tại mà không có giá trị của chúng?

Trên một số triển khai (mksh, freebsd / bin / sh), chỉ cần sử dụng exportchính nó sẽ phù hợp với hóa đơn:

$ export
FOO2
FOO

Nhưng đối với một số triển khai khác (bash, zsh, dash), exportcũng hiển thị giá trị. Với bash, ví dụ:

$ export
export FOO2='as  df\
  asdk=fja:\
asd=fa\
asdf'
export FOO='sjfkasjfd  kjasdf:\
   asdkj=fkajdsf:\
       :askjfkajsf=asdfkj:\
   safdkj'
$ printenv | sed -n l
FOO2=as\tdf\$
  asdk=fja:\$
asd=fa\$
asdf$
FOO=sjfkasjfd  kjasdf:\$
   asdkj=fkajdsf:\$
\t:askjfkajsf=asdfkj:\$
   safdkj$

Các tùy chọn khác như envhoặc printenvkhông có tùy chọn chỉ in tên biến mà không có giá trị, ít nhất là không phải trên nền tảng linux và freebsd mà tôi đã thử.

Đường ống đến awk / sed / vv. hoặc cắt xén danh sách với các kỹ thuật mở rộng tham số (ví dụ ${foo%%=*}:) có thể chấp nhận được, nhưng nó phải hoạt động với các giá trị có thể trải dài các dòng và có =và khoảng trắng trong giá trị (xem ví dụ ở trên).

Câu trả lời cụ thể cho việc triển khai shell cụ thể rất thú vị, nhưng tôi chủ yếu tìm kiếm thứ gì đó tương thích với các triển khai.


2
Nếu bạn định phân tích thứ gì đó, hãy đi với đầu ra export -pđược chỉ định bởi POSIX để tạo đầu ra cũng phù hợp với đầu vào trong trình bao.
Kusalananda

Tôi không cần bất cứ điều gì để nhập vào một vỏ. Tôi chỉ muốn tên của các biến môi trường. Vì vậy, hành trình bổ sung (ví dụ: từ 'xuất khẩu' ở phía trước của mỗi dòng) dù sao cũng sẽ phải bị xóa. Tại sao tôi muốn sử dụng export -pcho việc này?
Juan

1
Bạn muốn sử dụng export -pvì điều đó sẽ cung cấp cho bạn một đầu ra nhất quán trên tất cả các vỏ POSIX, mà bạn nói rằng bạn muốn.
Kusalananda

Tôi muốn một giải pháp sẽ chỉ in các tên biến là một giải pháp nhất quán trên các shell. export -pkhông phù hợp với yêu cầu đầu tiên - chỉ in tên biến mà không có giá trị.
Juan

NẾU bạn sẽ phân tích cái gì đó, đi với đầu ra của export -p. Tôi sẽ không viết phân tích cú pháp đó, vì trong trường hợp chung, nó cũng sẽ phải phân tích cú pháp trích dẫn thích hợp, trong trường hợp bạn có một biến có giá trị giống như thế hello\nexport var=value. Một trong số ít các lệnh khác sẽ cung cấp cho bạn đầu ra nhất quán trong tất cả các vỏ POSIX là env, nhưng đầu ra đó khó phân tích hơn vì nó thiếu export =bit.
Kusalananda

Câu trả lời:


9

Nó khá dễ dàng trong awk.

awk 'BEGIN{for(v in ENVIRON) print v}'

Tuy nhiên, hãy cẩn thận khi một số triển khai awk thêm các biến môi trường của riêng chúng (ví dụ GNU awk thêm AWKPATHAWKLIBPATHvào ENVIRON).

Đầu ra không rõ ràng nếu tên của một biến môi trường có chứa một dòng mới, điều này cực kỳ bất thường nhưng về mặt kỹ thuật là có thể. Một giải pháp sh tinh khiết sẽ là khó khăn. Đặt cược tốt nhất của bạn là bắt đầu với export -pnhưng xoa bóp nó trong sh thuần là khó khăn. Bạn có thể sử dụng sed để xoa bóp đầu ra export -p, sau đó sử dụng evalđể lấy vỏ để loại bỏ những gì nó được trích dẫn. Bash và zsh in tiền tố không chuẩn.

report () { echo "${1%%=*}"; };
eval "$(export -p | sed "s/^export /report /;
                         s/^declare -x /report /;
                         s/typeset -x /report /")"

Lưu ý rằng tùy thuộc vào shell, export -pcó thể hoặc không thể hiển thị các biến có tên không hợp lệ trong shell và nếu không, thì nó có thể hoặc không thể trích dẫn tên đúng. Ví dụ: các biến dash, mksh và zsh bỏ qua có tên bao gồm một dòng mới, BusyBox dash và ksh93 in chúng thô và bash in chúng thô mà không có giá trị của chúng. Nếu bạn cần bảo vệ chống lại đầu vào không đáng tin cậy, đừng dựa vào giải pháp POSIX thuần túy và chắc chắn không gọi evalbất cứ thứ gì có nguồn gốc từ đầu ra của export -p.


Tôi không chắc nó thực sự "dễ dàng" như thế nào với sed (1) với các giá trị đa dòng - tôi muốn thấy điều đó. Nhưng cảm ơn vì phương pháp awk (1). Tôi nghĩ rằng đây là cách di động nhất cho đến nay (mặc dù tôi không nghĩ exitlà cần thiết).
Juan

Lưu ý rằng nếu bạn nhận được FOO<newline>BAR, bạn không biết liệu đó là FOO<newline>BARbiến môi trường ( export -psẽ không hiển thị với hầu hết các shell, xem env $'FOO\nBAR=test' awk 'BEGIN{for (v in ENVIRON) print v}') hoặc cả biến FOOBARmôi trường.
Stéphane Chazelas

Lưu ý rằng GNU awkđặt các biến môi trường của riêng nó ( AWKPATHAWKLIBPATHtrên hệ thống của tôi)
Stéphane Chazelas

@ StéphaneChazelas - re: nhúng dòng mới vào tên var - đã đồng ý - khó bảo vệ chống lại điều đó với mã shell. Re: Ô nhiễm AWKPATH & AWKLIBPATH, tôi nhận thấy rằng chèn vào ngấm ngầm, quá. Đó là gnu awk, không phải bsd awk.
Juan

0

Tôi thích những điều đơn giản; điều này sẽ làm việc cho các hệ thống POSIX:

printenv | sed 's;=.*;;' | sort
HOME
HOSTNAME
PATH
PWD
SHLVL
TERM

5
export AAA=$'multi\nBBB=line'
roaima

@todd_dsm - Điều này không thành công đối với các biến môi trường có các giá trị trải dài hơn một dòng (ví dụ: đôi khi TERMCAP - Tôi thấy điều này khi trong phiên (1) màn hình, IIRC). Vì vậy, câu trả lời này không đáp ứng các yêu cầu được mô tả trong câu hỏi ban đầu. Tôi cũng thích đơn giản, nhưng điều này không hoạt động nói chung.
Juan

Các mẩu tin bạn đã chỉnh sửa trong bài viết gốc của bạn rất thú vị cho bash : compgen -e. Nó không giúp ích cho kịch bản di động của tôi (ví dụ: khi bash không có sẵn), nhưng nó rất thú vị.
Juan

Chỉ tò mò, tại sao lại giới hạn bản thân với vỏ bourne (posix)? tuân thủ posix là tuyệt vời nhưng bạn mất rất nhiều chức năng trong việc theo đuổi đó. bạn có thể di động và KHÔNG tuân thủ posix với bash; nó là một phần của gia đình GNU.
chập chững

Sử dụng dashtrong debian, tôi nhận được kết quả tương tự với lệnh ở trên hoặc, được sửa đổi printenv | sed 's;*=.;;' | sortđể lấy các giá trị. Tôi đã xuất biến yovà gán cho nó bình luận đầu tiên của bạn ở trên; Nó được in như mong đợi, với nhiều dòng. không chắc chắn những gì bạn đang trải qua nhưng không nên cắt đầu ra. chạy lệnh trong shell; bất cứ thứ gì nó xuất ra đều có cách nó hoạt động; mong đợi không cắt ngắn. Sau đó, trong bối cảnh TERMCAP / screen / iirc; nên giống nhau Nếu đầu ra không khớp thì có khả năng đó là một vấn đề với một trong những chương trình đó.
chập chững
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.