2013-03-22 25 views
7

Jestem trochę zdezorientowany, drukując zmienną, która zawiera nowy symbol linii w bashu.bash printf z nową linią

var="Age:\n20\ncolor:\nred" 
echo -e $var 
Age: 
20 
color: 
red 

To działa, ale wiele osób twierdzi, że echo z opcji jest not portable i it is better to use printf.

Nigdy nie użyłem prinf. Zgodnie z instrukcjami do emulacji polecenia echo:

printf '%s\n' "$var" 
Age:\n20\ncoloe:\nred 

Ale to nie parsuje \ n zmiennej wewnętrznej. instrukcje zazwyczaj mają ten przykład:

printf "Surname: %s\nName: %s\n" "$SURNAME" "$LASTNAME" 

Ale nie jest to mój przypadek iz mojego punktu widzenia nie jest wygodny w użyciu. I okazało się, że po prostu przez wpisanie mogę użyć tego:

printf "$ var \ n"

Czy to przenośny? Jeśli następnie przekażę $ var komendę mail, czy zapisze on nowe podziały wierszy?

printf "$var\n" | mail -s subj [email protected] 
+0

problem z 'printf' jest to, że powłoka wbudowane w niektórych muszli (bash i ksh93), ale proces zewnętrznego na innych (sh, ksh88, csh) . Zatem użycie 'printf' na starszych powłokach może spowolnić twój program, w zależności od tego ile razy go użyjesz. – cdarke

Odpowiedz

16

printf „s %b Format specifier została przeznaczona specjalnie do zastąpienia echo -e (faktycznie, rozszerzenie XSI do echo który wymaga szczególnej interpretacji argumentów domyślnie. -e nigdy nie został określony i jest niedozwolone przez POSIX.), i jest identyczny praktycznie pod każdym względem, w tym kilka różnic od $'...' i argumentu formatu w formacie do printf.

$ (var='Age:\n20\ncolor:\nred'; printf '%b\n' "$var") 
Age: 
20 
color: 
red 

Należy ogólnie unikać rozwija zmienne w ciągu formatu chyba że program kontroluje dokładną wartość i jest przeznaczony specjalnie do być ciągiem formatu. Twój ostatni przykład może być dość niebezpieczny w Bash z powodu opcji printf '.

# Bad! 
var='-v_[$(echo "oops, arbitrary code execution" >&2)0]' 
printf "$var" foo 

Zwykle jest dobra praktyka, aby uniknąć %b chyba że masz specjalne wymagania przenośności. Przechowywanie kodów ucieczki w zmiennej zamiast danych dosłownych narusza zasady separacji kodu i danych. Istnieją konteksty, w których jest to w porządku, ale zwykle lepiej jest przypisać wartość, używając cytowania, które jest określone dla następnej wersji POSIX i od dawna jest dostępne w Bash i większości smaków KHS.

x=$'foo\nbar'; printf '%s\n' "$x" # Good 
x=(foo bar); printf '%s\n' "${x[@]}" # Also good (depending on the goal) 
x='foo\nbar'; printf '%b\n' "$x"  # Ok, especially for compatibility 
x='foo\nbar'; printf -- "$x"   # Avoid if possible, without specific reason 
+0

Dziękuję za szczegółową odpowiedź. – idobr

+0

@ormaaj: Widziałem, że ktoś (ty?) Wspomniał o funkcjach, które zostaną dodane do następnej wersji POSIX-a; czy istnieje publicznie widoczny projekt tego? Po prostu ciekawy. – chepner

+0

@chepner Wersje robocze wersji roboczych są dostępne do wyświetlania subskrybentów. 2008 TC1 jest już sfinalizowany i powinien być już w każdej chwili, chociaż [to] (http://austingroupbugs.net/view.php?id=249) (i inne zmiany "funkcji") nie pojawi się, dopóki przynajmniej wydanie 7. Każdy może czytać archiwa list na [gmane] (http: //dir.gmane.org/gmane.comp.standards.posix.austin.general) lub wyszukaj narzędzie do śledzenia błędów. Teoretycznie, jeśli masz odpowiednie narzędzia, możesz skonstruować bieżący stan rzeczy z różnych błędów (nie próbowałem tego). – ormaaj