2014-12-08 10 views
5

Poszukuję bash jednej linijki, która dołącza znak nowej linii po każdym elemencie listy. Jeśli zgłoszę skrypt jako:Jak użyć podstawiania bash do dodania nowej linii na końcu każdego elementu listy

./script arg1 arg2 arg3 

Chcę wyjście być

arg1 
arg2 
arg3 

Próbowałem różnych odmian poniżej. Nowa linia nie zostanie dodana. Dodawany jest zwykły char.

# pretty much works except for an extra space 
list=${@/%/x} 
echo "$list" 

# appends 'n' 
list=${@/%/\n} 
echo "$list" 

# appends nothing 
list=${@/%/$'\n'} 
echo "$list" 

# appends nothing, \x078 would append 'x' 
list=${@/%/$'\x0D'} 
echo "$list" 

# appends nothing 
CR=$'\n' 
list=${@/%/$CR} 
echo "$list" 

# same issues with arrays 
tmp=([email protected]) 
list=${tmp/%/\n} 
echo "$list" 

Jaką poprawkę lub alternatywę sugerujesz? Oczywiście mogłem napisać pętlę lub zadzwonić, ale dokładnie to, co myślałem, że mogę uniknąć dzięki substytucji bash.

+0

Dlaczego starasz się uniknąć pętli? Może to niepotrzebnie skomplikować kod. Zasadniczo nie staraj się być tak sprytny, jak to możliwe i zachować rzeczy proste - https://en.wikipedia.org/wiki/KISS_principle. –

+1

Bo chcę skorzystać z ekspresji językowej. KISS jest dobry do unikania niepotrzebnej złożoności. Jaka jest złożoność ponownego formatowania listy argumentów? –

+1

Jeśli chodzi o _appends nothing part_: use quotes: 'list =" $ {@ /%/$ '\ n'} "; echo "lista $" '. –

Odpowiedz

5

Można użyć tej funkcji z "[email protected]":

f() { printf "%s\n" "[email protected]"; } 
f arg1 arg2 arg3 
arg1 
arg2 
arg3 

Zgodnie man bash

@ Expands to the positional parameters, starting from one. When the expansion occurs 
    within double quotes, each parameter expands to a separate word. That is, "[email protected]" is 
    equivalent to "$1" "$2" ... 
+0

Schludny! Sądzę, że skupiłem się zbytnio na substytucji, aby myśleć o printf. Nadal chciałbym wiedzieć, dlaczego substytucja nie działa, jeśli ktoś ma ochotę odpowiedzieć na tę część. –

+0

Nie należy owijać printf wewnątrz funkcji btw. sam printf działa bardzo dobrze, ponieważ "$ @" jest najpierw rozszerzany. –

+0

Tak, to prawda, użyłem funkcji tylko do celów demo kodu. Zamierzeniem było zawsze użycie 'printf'. Aby odpowiedzieć na pierwsze pytanie, możesz użyć: 's =" $ @ "; echo "$ {s ///$ '\ n'}"; 'dla ** podstawienia **. – anubhava

2

printf byłaby moja odpowiedź również. Inną techniką jest użycie IFS:

$ IFS=$'\n' 
$ list="$*" 
$ echo "$list" 
arg1 
arg2 
arg3 

Uwagi:

  • wykorzystuje ANSI-C cytowanie dla sekwencji nowej linii
  • "$*" (with the quotes, ważne) łączy pozycyjnych params przy użyciu pierwszego char z $ IFS
  • zacytuj zmienną powłoki dla polecenia echo, aby zachować wewnętrzne znaki nowej linii.

To na nowo definiuje wartość IFS dla bieżącej powłoki. Można zapisać starą wartość pierwszy i przywrócić go po:

oldIFS=$IFS; IFS=$'\n'; list="$*"; IFS=$oldIFS 

lub użyć podpowłoce więc modyfikacja jest odrzucana dla Ciebie:

$ list=$(IFS=$'\n'; echo "$*") 
Powiązane problemy