2013-07-29 30 views
6

thời gian gần đây tôi phát hiện ra một số bash mã mà sử dụng ít được biết đến (tốt, ít được biết đến tôi anyway) tính năng của chức năng chuyển hướng, chẳng hạn như đơn giản hóa đáng kể:Làm thế nào bạn có thể ghi đè chuyển hướng hàm trong bash?

function xyzzy() { 
    echo hello 
} >/dev/null 

Khi bạn gọi hàm với một đơn giản xyzzy, nó sẽ tự động áp dụng các chuyển hướng gắn liền với chức năng bất kể những gì bạn đã làm khi gọi nó.

Điều tôi muốn biết là có cách nào để ghi đè hành vi này trong cuộc gọi đến chính hàm đó, để xem thông báo được tạo. Tôi cố gắng thay đổi tập tin chứa tất cả các chức năng vì (1) nó lớn, (2) nó thay đổi thường xuyên, và (3) nó được bảo vệ rất nhiều bởi nhóm hỗ trợ nó.

Tôi đã thử:

xyzzy >&1 

để cố gắng ghi đè lên nó nhưng sản lượng vẫn không hiển thị (có thể vì >&1 có thể được coi là một không-op).


Nói cách khác, đưa ra kịch bản:

function xyzzy() { 
    echo hello 
} >/tmp/junk 

rm -f /tmp/junk 
echo ================ 
echo Standard output 
echo ---------------- 
xyzzy # something else here 
echo ================ 
echo Function capture 
echo ---------------- 
cat /tmp/junk 
echo ================ 

nó hiện kết quả đầu ra:

================ 
Standard output 
---------------- 
================ 
Function capture 
---------------- 
hello 
================ 

tôi có thể thay đổi gì cuộc gọi xyzzy tới, để có được hello in trong phần đầu ra tiêu chuẩn hơn là phần chụp chức năng?

Và điều này cần phải được mà không cố gắng để đọc các tập tin /tmp/junk sau khi nó được tạo ra kể từ khi thực tế chuyển hướng có thể là /dev/null vì vậy họ sẽ không được trong một tập tin.

+0

Nhận xét không hữu ích: Tôi đã thử 'xyzzy 1>/tmp/aaa' và tệp được chạm vào nhưng không được lấp đầy dữ liệu. Nó có hành vi tương tự như 'xyzzy 2>/tmp/aaa'. – fedorqui

+0

có thể đáng để hỏi điều này trên http://unix.stackexchange.com. – dogbane

+0

@dogbane, tôi đã bị rách vì điều đó có vẻ như cả lập trình _and_ Unix. Tôi không muốn tiền đồn nhưng, nếu tôi không thể nhận được câu trả lời ở đây, tôi cho rằng tôi có thể thử nó ở đó sau này. – paxdiablo

Trả lời

2

Điều duy nhất tôi nghĩ là có thể phân tích đầu ra của declare -f function_name và xóa chuyển hướng.

Đây có lẽ là cách tiếp cận dễ dàng nhất. Lưu ý rằng bạn cần điều chỉnh tập lệnh awk cho bố cục chức năng cụ thể và nó không sửa đổi phần thân của hàm. Điều đó có nghĩa là bạn chỉ có thể tắt chuyển hướng ở cấp cao nhất. Bạn có thể sửa đổi toàn bộ cây cuộc gọi của chức năng để tắt chuyển hướng nhưng điều đó sẽ yêu cầu trình phân tích cú pháp bash có khả năng nhận dạng và thay đổi các cuộc gọi hàm trong nội dung.

Tập lệnh sau cho biết cách thực hiện với chức năng mẫu của bạn.Tất cả các lệnh awk nào là tạo một hàm mới my_xyzzy mà phản ánh xyzzy chức năng ngoại trừ dòng cuối cùng, có hiệu quả biến nó thành:

function my_xyzzy() { 
    echo hello 
} 

Và kịch bản hoàn chỉnh theo thông số kỹ thuật:

function xyzzy() { 
    echo hello 
} >/tmp/qqqq 

declare -f xyzzy | awk ' 
    NR==1 {print "my_xyzzy()"} 
    NR==2 {prev=$0} 
    NR>2 {print prev;prev=$0} 
    END {print "}"}' >$$.bash 
. $$.bash 
rm -f $$.bash 

rm -f /tmp/qqqq 
echo ================ 
echo Standard output 
echo ---------------- 
my_xyzzy 
echo ================ 
echo Function capture 
echo ---------------- 
cat /tmp/qqqq 
echo ================ 

Các đầu ra của điều đó là:

================ 
Standard output 
---------------- 
hello 
================ 
Function capture 
---------------- 
cat: /tmp/qqqq: No such file or directory 
================ 
+0

Tôi đã thực sự đưa ra một số mặc dù điều này theo một cách hơi khác, bằng cách chuyển các tập tin kịch bản thực tế với các chức năng trong nó thông qua một bộ lọc thay đổi tất cả các định nghĩa chức năng và các cuộc gọi đến một cái gì đó như 'my_xyzzy' và sau đó tìm nguồn cung ứng _that._ vị trí dự phòng nếu tôi không thể tìm thấy cách dễ dàng để ghi đè chuyển hướng, vì nó sẽ yêu cầu một trình phân tích cú pháp khá phức tạp để nắm bắt tất cả các trường hợp cạnh. – paxdiablo

+0

Glenn, tôi bắt đầu tìm cách tạo biến thể 'bash' của riêng mình mà sẽ không chuyển hướng các hàm nếu một biến được đặt (tôi không thể thay đổi tập lệnh nhưng chạy nó với một bash' được sửa đổi một chút) nhưng nó cũng đã trở thành cứng. Vì vậy, tôi nghi ngờ rằng đây là cách tôi sẽ phải đi. Tôi đã thêm các phát hiện của tôi vào câu trả lời của bạn để làm tròn nó ra một chút. – paxdiablo

0

Tôi không nghĩ rằng chuyển hướng chức năng Bash có thể bị ghi đè tự động trong cuộc gọi đến chính hàm đó mặc dù bối cảnh vỏ tạm thời bị thay đổi có thể được sử dụng bằng cách kết hợp Bash aliasesfunctions (xem Magic Aliases: A Layering Loophole in the Bourne Shell).

Không động, nó là biểu thức chuyển hướng cuối cùng, i. e. một trong cùng bên phải, ghi đè lên những cái trước đó nếu các biểu thức chuyển hướng tham chiếu đến cùng một bộ mô tả tệp.

# example 
ls -ld/no_such_file 1>/dev/null 1>/dev/tty 1>&2 1>redirtest.txt 
cat redirtest.txt 

Do đó, đề nghị glenn jackman 's sử dụng declare -f function_name vẻ như cách để thêm một biểu stdout chuyển hướng cuối cùng để ghi đè lên những người trước đây.

xyzzy() { echo 'Hello, world!'; } 1>/dev/null 
#func="$(declare -f xyzzy) 1>&2" 
func="$(declare -f xyzzy) 1>/dev/tty" 
eval "$func" 
xyzzy 
Các vấn đề liên quan