Jak używasz linii kontynuacji basha?
Zdaję sobie sprawę, że możesz to zrobić:
echo "continuation \
lines"
>continuation lines
Jeśli jednak masz wcięty kod, to nie działa tak dobrze:
echo "continuation \
lines"
>continuation lines
Jak używasz linii kontynuacji basha?
Zdaję sobie sprawę, że możesz to zrobić:
echo "continuation \
lines"
>continuation lines
Jeśli jednak masz wcięty kod, to nie działa tak dobrze:
echo "continuation \
lines"
>continuation lines
Odpowiedzi:
To jest to, czego możesz chcieć
$ echo "continuation"\
> "lines"
continuation lines
Jeśli tworzy to dwa argumenty do powtórzenia, a chcesz tylko jeden, spójrzmy na konkatenację ciągów. W bash, umieszczenie dwóch ciągów obok siebie, konkatenacja:
$ echo "continuation""lines"
continuationlines
Tak więc linia kontynuacji bez wcięcia jest jednym ze sposobów na podzielenie łańcucha:
$ echo "continuation"\
> "lines"
continuationlines
Ale kiedy używane jest wcięcie:
$ echo "continuation"\
> "lines"
continuation lines
Otrzymujesz dwa argumenty, ponieważ nie jest to już konkatenacja.
Jeśli chciałbyś, aby pojedynczy ciąg, który przecinał linie, jednocześnie wciskając wszystkie te spacje, ale nie uzyskując wszystkich tych spacji, możesz spróbować porzucić linię kontynuacji i użyć zmiennych:
$ a="continuation"
$ b="lines"
$ echo $a$b
continuationlines
Umożliwi to uzyskanie czystego wcięcia kodu kosztem dodatkowych zmiennych. Jeśli zmienisz zmienne lokalnymi, nie powinno być tak źle.
s="string no. 1" s+="string no. 2" s+=" string no. 3" echo "$s"
Tutaj dokumenty z <<-HERE
terminatorem działają dobrze w przypadku wciętych wieloliniowych ciągów tekstowych. Spowoduje to usunięcie wszystkich wiodących zakładek z tego dokumentu. (Terminatory linii pozostaną jednak nadal.)
cat <<-____HERE
continuation
lines
____HERE
Zobacz także http://ss64.com/bash/syntax-here.html
Jeśli chcesz zachować niektóre, ale nie wszystkie, początkowe spacje, możesz użyć czegoś takiego jak
sed 's/^ //' <<____HERE
This has four leading spaces.
Two of them will be removed by sed.
____HERE
a może użyj, tr
aby pozbyć się nowych linii:
tr -d '\012' <<-____
continuation
lines
____
(Druga linia ma zakładkę i spację z przodu; tabulator zostanie usunięty przez operatora myślnika przed terminatorem heredoc, podczas gdy spacja zostanie zachowana.)
Do owijania długich, złożonych ciągów w wielu liniach lubię printf
:
printf '%s' \
"This will all be printed on a " \
"single line (because the format string " \
"doesn't specify any newline)"
Działa również dobrze w kontekstach, w których chcesz osadzić nietrywialne fragmenty skryptu powłoki w innym języku, w którym składnia języka hosta nie pozwala na użycie dokumentu tutaj, na przykład w Makefile
lub Dockerfile
.
printf '%s\n' >./myscript \
'#!/bin/sh` \
"echo \"G'day, World\"" \
'date +%F\ %T' && \
chmod a+x ./myscript && \
./myscript
printf
przykład teraz.)
Możesz używać tablic bash
$ str_array=("continuation"
"lines")
następnie
$ echo "${str_array[*]}"
continuation lines
jest dodatkowa spacja, ponieważ (po instrukcji bash):
Jeśli słowo jest umieszczone w cudzysłowie,
${name[*]}
rozwija się do pojedynczego słowa z wartością każdego elementu tablicy oddzieloną pierwszym znakiem zmiennej IFS
Więc ustaw, IFS=''
aby pozbyć się dodatkowej przestrzeni
$ IFS=''
$ echo "${str_array[*]}"
continuationlines
W niektórych scenariuszach użycie zdolności konkatenacji Bash może być odpowiednie.
temp='this string is very long '
temp+='so I will separate it onto multiple lines'
echo $temp
this string is very long so I will separate it onto multiple lines
name = [wartość] ...
... W kontekście, w którym instrukcja przypisania przypisuje wartość do zmiennej powłoki lub indeksu tablicy, operator + = może być użyty do dołączenia lub dodania do poprzedniej wartości zmiennej. Gdy + = zostanie zastosowane do zmiennej, dla której ustawiono atrybut liczby całkowitej, wartość jest oceniana jako wyrażenie arytmetyczne i dodawana do bieżącej wartości zmiennej, która również jest oceniana. Gdy + = zostanie zastosowane do zmiennej tablicowej przy użyciu przypisania złożonego (zobacz Tablice poniżej), wartość zmiennej nie jest nieustawiona (tak jak to ma miejsce w przypadku użycia =), a nowe wartości są dołączane do tablicy, zaczynając o jeden większy niż maksymalny indeks tablicy (dla tablic indeksowanych) lub dodane jako dodatkowe pary klucz-wartość w tablicy asocjacyjnej. Po zastosowaniu do zmiennej o wartości łańcuchowej wartość jest rozwijana i dołączana do wartości zmiennej.
Natknąłem się na sytuację, w której musiałem wysłać długą wiadomość jako część argumentu polecenia i musiałem przestrzegać ograniczenia długości linii. Polecenia wyglądają mniej więcej tak:
somecommand --message="I am a long message" args
Sposób, w jaki to rozwiązałem, to przeniesienie wiadomości jako dokumentu tutaj (jak sugerował @tripleee). Ale tutaj dokument staje się standardem, więc należy go ponownie przeczytać, poszedłem z poniższym podejściem:
message=$(
tr "\n" " " <<- END
This is a
long message
END
)
somecommand --message="$message" args
Ma to tę zaletę, że $message
może być użyte dokładnie jako stała łańcuchowa bez dodatkowych białych znaków lub znaków końca wiersza.
Zauważ, że wszystkie powyższe wiersze wiadomości są poprzedzone znakiem tab
, który jest usuwany w tym dokumencie (z powodu użycia <<-
). Na końcu nadal znajdują się podziały wierszy, które są następnie zastępowane dd
spacjami.
Zauważ również, że jeśli nie usuniesz nowych linii, będą one wyglądały tak, jak "$message"
są rozwinięte. W niektórych przypadkach możesz obejść ten problem, usuwając podwójne cudzysłowy $message
, ale wiadomość nie będzie już pojedynczym argumentem.
Kontynuację linii można również osiągnąć poprzez sprytne użycie składni.
W przypadku echo
:
# echo '-n' flag prevents trailing <CR>
echo -n "This is my one-line statement" ;
echo -n " that I would like to make."
This is my one-line statement that I would like to make.
W przypadku vars:
outp="This is my one-line statement" ;
outp+=" that I would like to make." ;
echo -n "${outp}"
This is my one-line statement that I would like to make.
Inne podejście w przypadku vars:
outp="This is my one-line statement" ;
outp="${outp} that I would like to make." ;
echo -n "${outp}"
This is my one-line statement that I would like to make.
Voila!
Możesz po prostu oddzielić go znakami nowej linii (bez używania odwrotnego ukośnika) zgodnie z wymaganiami w ramach wcięcia w następujący sposób i po prostu usunąć nowe linie.
Przykład:
echo "continuation
of
lines" | tr '\n' ' '
Lub jeśli jest to zmienna definicja nowej linii jest automatycznie konwertowana na spacje. Tak więc, pasek dodatkowych spacji tylko jeśli ma to zastosowanie.
x="continuation
of multiple
lines"
y="red|blue|
green|yellow"
echo $x # This will do as the converted space actually is meaningful
echo $y | tr -d ' ' # Stripping of space may be preferable in this case
Nie jest to dokładnie to, o co prosił użytkownik, ale innym sposobem na utworzenie długiego ciągu, który obejmuje wiele wierszy, jest jego przyrostowe tworzenie, na przykład:
$ greeting="Hello"
$ greeting="$greeting, World"
$ echo $greeting
Hello, World
Oczywiście w tym przypadku byłoby łatwiej zbudować go za jednym zamachem, ale ten styl może być bardzo lekki i zrozumiały, gdy mamy do czynienia z dłuższymi strunami.
Jeśli jednak masz wcięty kod, to nie działa tak dobrze:
echo "continuation \ lines" >continuation lines
Spróbuj z pojedynczymi cudzysłowami i połącz łańcuchy:
echo 'continuation' \
'lines'
>continuation lines
Uwaga: konkatenacja zawiera spacje.
echo
jeśli miał x=
, to pojawi się błąd: lines: command not found
.
W zależności od tego, jakie rodzaje ryzyka zaakceptujesz oraz jak dobrze znasz dane i im ufasz, możesz użyć uproszczonej interpolacji zmiennych.
$: x="
this
is
variably indented
stuff
"
$: echo "$x" # preserves the newlines and spacing
this
is
variably indented
stuff
$: echo $x # no quotes, stacks it "neatly" with minimal spacing
this is variably indented stuff
To prawdopodobnie nie jest odpowiedzią na Twoje pytanie, ale i tak może Ci się przydać.
Pierwsze polecenie tworzy skrypt, który jest wyświetlany przez drugie polecenie.
Trzecie polecenie sprawia, że skrypt jest wykonywalny.
Czwarte polecenie zawiera przykład użycia.
john@malkovich:~/tmp/so$ echo $'#!/usr/bin/env python\nimport textwrap, sys\n\ndef bash_dedent(text):\n """Dedent all but the first line in the passed `text`."""\n try:\n first, rest = text.split("\\n", 1)\n return "\\n".join([first, textwrap.dedent(rest)])\n except ValueError:\n return text # single-line string\n\nprint bash_dedent(sys.argv[1])' > bash_dedent
john@malkovich:~/tmp/so$ cat bash_dedent
#!/usr/bin/env python
import textwrap, sys
def bash_dedent(text):
"""Dedent all but the first line in the passed `text`."""
try:
first, rest = text.split("\n", 1)
return "\n".join([first, textwrap.dedent(rest)])
except ValueError:
return text # single-line string
print bash_dedent(sys.argv[1])
john@malkovich:~/tmp/so$ chmod a+x bash_dedent
john@malkovich:~/tmp/so$ echo "$(./bash_dedent "first line
> second line
> third line")"
first line
second line
third line
Zwróć uwagę, że jeśli naprawdę chcesz użyć tego skryptu, bardziej sensowne jest przeniesienie wykonywalnego skryptu do programu ~/bin
, aby znalazł się na Twojej ścieżce.
Sprawdź dokumentację Pythona, aby uzyskać szczegółowe informacje o tym, jak textwrap.dedent
działa.
Jeśli użycie $'...'
lub "$(...)"
jest dla Ciebie mylące, zadaj kolejne pytanie (jedno na konstrukcję), jeśli jeszcze takiego nie ma. Dobrze byłoby podać link do znalezionego / zadanego pytania, aby inne osoby miały odnośnik.