Jak działa "cat
Musiałem napisać skrypt, aby wprowadzić wejście Wielowierszowe do programu (psql
).
Po odrobinie googlowania znalazłem następującą składnię:
cat << EOF | psql ---params
BEGIN;
`pg_dump ----something`
update table .... statement ...;
END;
EOF
To poprawnie konstruuje ciąg wielowierszowy (od BEGIN;
do END;
, włącznie) i przekazuje go jako wejście do psql
.
Ale nie mam pojęcia jak/dlaczego to działa, czy ktoś może wyjaśnić?
Mam na myśli głównie cat << EOF
, wiem >
wyjścia do pliku, >>
dołącza do pliku, <
odczytuje wejście z plik.
Co dokładnie robi <<
?
I czy jest do tego jakaś strona podręcznika?
424
Author: Benjamin W., 2010-03-23
7 answers
To się nazywa heredoc format zapewniający ciąg znaków na stdin. Zobacz https://en.wikipedia.org/wiki/Here_document#Unix_shells Po Więcej Szczegółów.
From man bash
:
Tutaj Dokumenty
Ten typ przekierowania nakazuje powłoce odczytywanie danych wejściowych z
źródło prądu aż do linii
zawierające tylko słowo (bez końców
blanki) jest widoczne.
Wszystkie linie odczytane do tego punktu są następnie używane jako na
standardowe wejście dla polecenia.
Format Dokumentów tutaj jest:
<<[-]word
here-document
delimiter
Brak rozszerzania parametrów, zastępowania poleceń, rozszerzania arytmetycznego lub
rozszerzenie pathname jest wykonywane na
słowo . Jeśli dowolne znaki w słowie są
quoted, the
ogranicznik jest wynikiem usuwania cudzysłowu na wyrazie , A linie
w tutaj-dokument nie są rozszerzane.
Jeśli słowo nie jest cytowane, wszystkie linie
tutaj-dokument są poddawane rozbudowie parametrów, polecenie
podstawienie i arytmetyka
ekspansja. W tym ostatnim przypadku
sekwencja znaków \<newline>
jest
ignorowane i \
muszą być użyte do cytowania znaków \
, $
, i `
.
Jeśli operatorem przekierowania jest <<-
, to wszystkie znaki tabulacji
są usuwane z linii wejściowych i
linia zawierająca ogranicznik . To
pozwala tutaj-dokumenty wewnątrz skryptów powłoki być wcięte w naturalna Moda.
376
Author: kennytm,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-26 04:53:16
Składnia cat <<EOF
jest bardzo przydatna podczas pracy z tekstem wielowierszowym w Bash, np. podczas przypisywania wielowierszowego łańcucha do zmiennej powłoki, pliku lub potoku.
Przykłady użycia składni cat <<EOF
w Bash:
1. Przypisanie wielowierszowego łańcucha do zmiennej powłoki
$ sql=$(cat <<EOF
SELECT foo, bar FROM db
WHERE foo='baz'
EOF
)
zmienna $sql
zawiera teraz również znaki nowej linii. Możesz sprawdzić za pomocą echo -e "$sql"
.
2. Przekazywanie ciągów wielowierszowych do pliku w Bash
$ cat <<EOF > print.sh
#!/bin/bash
echo \$PWD
echo $PWD
EOF
print.sh
plik teraz zawiera:
#!/bin/bash
echo $PWD
echo /home/user
3. Przekazuj ciąg wielowierszowy do rury w Bash
$ cat <<EOF | grep 'b' | tee b.txt
foo
bar
baz
EOF
plik b.txt
zawiera linie bar
i baz
. To samo wyjście jest drukowane do stdout
.
343
Author: Vojtech Vitek,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-14 22:01:53
W Twoim przypadku, " EOF "jest znany jako "tutaj Tag". Zasadniczo <<Here
mówi powłoce, że zamierzasz wprowadzić ciąg wielowierszowy aż do "znacznika" Here
. Możesz nazwać ten tag jak chcesz, często jest to EOF
lub STOP
.
Niektóre zasady dotyczące tagów tutaj:
- znacznik może być dowolnym ciągiem znaków, wielkimi lub małymi literami, chociaż większość ludzi używa wielkich liter zgodnie z konwencją.
- znacznik nie będzie uważany za znacznik Here, jeśli w tej linii znajdują się inne słowa. W takim przypadku będzie / align = "left" / Znacznik powinien znajdować się sam w osobnej linii, aby można go było uznać za znacznik.
- znacznik nie powinien mieć spacji wiodącej ani końcowej w tej linii, aby można go było uznać za znacznik. W przeciwnym razie będzie on uważany za część ciągu znaków.
Przykład:
$ cat >> test <<HERE
> Hello world HERE <-- Not by itself on a separate line -> not considered end of string
> This is a test
> HERE <-- Leading space, so not considered end of string
> and a new line
> HERE <-- Now we have the end of the string
157
Author: edelans,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-02 09:31:14
POSIX 7
Kennytm cytuje man bash
, ale większość z nich to również POSIX 7: http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_07_04 :
Operatory przekierowujące "
Tutaj-dokument jest traktowany jako pojedyncze słowo, które zaczyna się po następnym i trwa aż do linia zawierająca tylko ogranicznik i a, bez znaków pomiędzy nimi. Następnie rozpoczyna się następny dokument tutaj, jeśli taki istnieje. Format jest następujący:
[n]<<word
here-document
delimiter
Gdzie opcjonalne n reprezentuje numer deskryptora pliku. Jeśli liczba jest pominięta, dokument here odnosi się do standardowego wejścia (deskryptor pliku 0).
Jeśli jakikolwiek znak w programie word jest cytowany, ogranicznik tworzy się poprzez usunięcie cudzysłowu w programie word, a linie here-document nie być rozszerzony. W przeciwnym razie ogranicznikiem jest samo słowo.
Jeśli żadne znaki w programie word nie są cytowane, wszystkie linie dokumentu here powinny zostać rozszerzone w celu rozszerzenia parametrów, zastąpienia poleceń i rozszerzenia arytmetycznego. W tym przypadku wejście zachowuje się jak wewnętrzne podwójne cudzysłowy (zobacz podwójne cudzysłowy). Jednak znak podwójnego cytowania ( "" ) nie jest traktowany specjalnie w dokumencie here, z wyjątkiem sytuacji, gdy podwójny cytat pojawia się w dokumencie here "$()", "`", lub "${}".
Jeśli symbolem przekierowania jest"<tab> są usuwane z linii wejściowych i linii zawierającej ogranicznik końcowy. Jeżeli w wierszu podano więcej niż jeden operator "
Gdy dokument here jest odczytywany z urządzenia końcowego i powłoka jest interaktywna, zapisuje zawartość zmiennej PS2, przetworzonej w sposób opisany w zmiennych powłoki, do standardowego błędu przed odczytaniem każdej linii wejścia, aż do rozpoznania ogranicznika.
Przykłady
Niektóre przykłady jeszcze nie podane.
Cudzysłowy zapobiegają rozszerzaniu parametrów
Bez cudzysłowów:
a=0
cat <<EOF
$a
EOF
Wyjście:
0
Z cytatami:
a=0
cat <<'EOF'
$a
EOF
Lub (brzydki, ale ważny):
a=0
cat <<E"O"F
$a
EOF
Wyjścia:
$a
Myślnik usuwa początek tabs
Bez myślnika:
cat <<EOF
<tab>a
EOF
Gdzie <tab>
jest literalną tabulatorem i można ją wstawić za pomocą Ctrl + V <tab>
Wyjście:
<tab>a
Z myślnikiem:
cat <<-EOF
<tab>a
<tab>EOF
Wyjście:
a
Istnieje to oczywiście po to, abyś mógł wciąć swój cat
jak otaczający kod, który jest łatwiejszy do odczytania i utrzymania. Np.:
if true; then
cat <<-EOF
a
EOF
fi
Niestety, nie działa to dla znaków spacji: POSIX faworyzował tab
wcięcia tutaj. Kurczę.
47
Author: Ciro Santilli 新疆改造中心 六四事件 法轮功,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-25 14:51:36
Używanie tee zamiast cat
Nie do końca jako odpowiedź na pierwotne pytanie, ale i tak chciałem się tym podzielić: miałem potrzebę utworzenia pliku konfiguracyjnego w katalogu, który wymagał praw roota.
W tym przypadku nie działa:
$ sudo cat <<EOF >/etc/somedir/foo.conf
# my config file
foo=bar
EOF
Ponieważ przekierowanie jest obsługiwane poza kontekstem sudo.
Zamiast tego użyłem tego:
$ sudo tee <<EOF /etc/somedir/foo.conf >/dev/null
# my config file
foo=bar
EOF
16
Author: Andreas Maier,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-13 12:14:06
Niekoniecznie jest to odpowiedź na pierwotne pytanie, ale dzielenie się wynikami z moich własnych testów. To:
<<test > print.sh
#!/bin/bash
echo \$PWD
echo $PWD
test
Wytworzy ten sam plik co:
cat <<test > print.sh
#!/bin/bash
echo \$PWD
echo $PWD
test
Nie widzę sensu używania komendy cat.
Warto zauważyć, że tutaj dokumenty działają również w pętlach bash.
Ten przykład pokazuje, jak uzyskać listę kolumn tabeli:
export postgres_db_name='my_db'
export table_name='my_table_name'
# start copy
while read -r c; do test -z "$c" || echo $table_name.$c , ; done < <(cat << EOF | psql -t -q -d $postgres_db_name -v table_name="${table_name:-}"
SELECT column_name
FROM information_schema.columns
WHERE 1=1
AND table_schema = 'public'
AND table_name =:'table_name' ;
EOF
)
# stop copy , now paste straight into the bash shell ...
output:
my_table_name.guid ,
my_table_name.id ,
my_table_name.level ,
my_table_name.seq ,
Lub nawet bez nowej linii
while read -r c; do test -z "$c" || echo $table_name.$c , | perl -ne
's/\n//gm;print' ; done < <(cat << EOF | psql -t -q -d $postgres_db_name -v table_name="${table_name:-}"
SELECT column_name
FROM information_schema.columns
WHERE 1=1
AND table_schema = 'public'
AND table_name =:'table_name' ;
EOF
)
# output: daily_issues.guid ,daily_issues.id ,daily_issues.level ,daily_issues.seq ,daily_issues.prio ,daily_issues.weight ,daily_issues.status ,daily_issues.category ,daily_issues.name ,daily_issues.description ,daily_issues.type ,daily_issues.owner
0
Author: Yordan Georgiev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-14 15:18:35
Musiałem napisać skrypt, aby wprowadzić wejście Wielowierszowe do programu (psql
).
Po odrobinie googlowania znalazłem następującą składnię:
cat << EOF | psql ---params
BEGIN;
`pg_dump ----something`
update table .... statement ...;
END;
EOF
To poprawnie konstruuje ciąg wielowierszowy (od BEGIN;
do END;
, włącznie) i przekazuje go jako wejście do psql
.
Ale nie mam pojęcia jak/dlaczego to działa, czy ktoś może wyjaśnić?
Mam na myśli głównie cat << EOF
, wiem >
wyjścia do pliku, >>
dołącza do pliku, <
odczytuje wejście z plik.
Co dokładnie robi <<
?
I czy jest do tego jakaś strona podręcznika?
7 answers
To się nazywa heredoc format zapewniający ciąg znaków na stdin. Zobacz https://en.wikipedia.org/wiki/Here_document#Unix_shells Po Więcej Szczegółów.
From man bash
:
Tutaj Dokumenty
Ten typ przekierowania nakazuje powłoce odczytywanie danych wejściowych z źródło prądu aż do linii zawierające tylko słowo (bez końców blanki) jest widoczne.
Wszystkie linie odczytane do tego punktu są następnie używane jako na standardowe wejście dla polecenia.
Format Dokumentów tutaj jest:
<<[-]word here-document delimiter
Brak rozszerzania parametrów, zastępowania poleceń, rozszerzania arytmetycznego lub rozszerzenie pathname jest wykonywane na słowo . Jeśli dowolne znaki w słowie są quoted, the ogranicznik jest wynikiem usuwania cudzysłowu na wyrazie , A linie w tutaj-dokument nie są rozszerzane. Jeśli słowo nie jest cytowane, wszystkie linie tutaj-dokument są poddawane rozbudowie parametrów, polecenie podstawienie i arytmetyka ekspansja. W tym ostatnim przypadku sekwencja znaków
\<newline>
jest ignorowane i\
muszą być użyte do cytowania znaków\
,$
, i`
.Jeśli operatorem przekierowania jest
<<-
, to wszystkie znaki tabulacji są usuwane z linii wejściowych i linia zawierająca ogranicznik . To pozwala tutaj-dokumenty wewnątrz skryptów powłoki być wcięte w naturalna Moda.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-26 04:53:16
Składnia cat <<EOF
jest bardzo przydatna podczas pracy z tekstem wielowierszowym w Bash, np. podczas przypisywania wielowierszowego łańcucha do zmiennej powłoki, pliku lub potoku.
Przykłady użycia składni cat <<EOF
w Bash:
1. Przypisanie wielowierszowego łańcucha do zmiennej powłoki
$ sql=$(cat <<EOF
SELECT foo, bar FROM db
WHERE foo='baz'
EOF
)
zmienna $sql
zawiera teraz również znaki nowej linii. Możesz sprawdzić za pomocą echo -e "$sql"
.
2. Przekazywanie ciągów wielowierszowych do pliku w Bash
$ cat <<EOF > print.sh
#!/bin/bash
echo \$PWD
echo $PWD
EOF
print.sh
plik teraz zawiera:
#!/bin/bash
echo $PWD
echo /home/user
3. Przekazuj ciąg wielowierszowy do rury w Bash
$ cat <<EOF | grep 'b' | tee b.txt
foo
bar
baz
EOF
plik b.txt
zawiera linie bar
i baz
. To samo wyjście jest drukowane do stdout
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-14 22:01:53
W Twoim przypadku, " EOF "jest znany jako "tutaj Tag". Zasadniczo <<Here
mówi powłoce, że zamierzasz wprowadzić ciąg wielowierszowy aż do "znacznika" Here
. Możesz nazwać ten tag jak chcesz, często jest to EOF
lub STOP
.
Niektóre zasady dotyczące tagów tutaj:
- znacznik może być dowolnym ciągiem znaków, wielkimi lub małymi literami, chociaż większość ludzi używa wielkich liter zgodnie z konwencją.
- znacznik nie będzie uważany za znacznik Here, jeśli w tej linii znajdują się inne słowa. W takim przypadku będzie / align = "left" / Znacznik powinien znajdować się sam w osobnej linii, aby można go było uznać za znacznik.
- znacznik nie powinien mieć spacji wiodącej ani końcowej w tej linii, aby można go było uznać za znacznik. W przeciwnym razie będzie on uważany za część ciągu znaków.
Przykład:
$ cat >> test <<HERE
> Hello world HERE <-- Not by itself on a separate line -> not considered end of string
> This is a test
> HERE <-- Leading space, so not considered end of string
> and a new line
> HERE <-- Now we have the end of the string
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-02 09:31:14
POSIX 7
Kennytm cytuje man bash
, ale większość z nich to również POSIX 7: http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_07_04 :
Operatory przekierowujące "
Tutaj-dokument jest traktowany jako pojedyncze słowo, które zaczyna się po następnym i trwa aż do linia zawierająca tylko ogranicznik i a, bez znaków pomiędzy nimi. Następnie rozpoczyna się następny dokument tutaj, jeśli taki istnieje. Format jest następujący:
[n]<<word
here-document
delimiter
Gdzie opcjonalne n reprezentuje numer deskryptora pliku. Jeśli liczba jest pominięta, dokument here odnosi się do standardowego wejścia (deskryptor pliku 0).
Jeśli jakikolwiek znak w programie word jest cytowany, ogranicznik tworzy się poprzez usunięcie cudzysłowu w programie word, a linie here-document nie być rozszerzony. W przeciwnym razie ogranicznikiem jest samo słowo.
Jeśli żadne znaki w programie word nie są cytowane, wszystkie linie dokumentu here powinny zostać rozszerzone w celu rozszerzenia parametrów, zastąpienia poleceń i rozszerzenia arytmetycznego. W tym przypadku wejście zachowuje się jak wewnętrzne podwójne cudzysłowy (zobacz podwójne cudzysłowy). Jednak znak podwójnego cytowania ( "" ) nie jest traktowany specjalnie w dokumencie here, z wyjątkiem sytuacji, gdy podwójny cytat pojawia się w dokumencie here "$()", "`", lub "${}".
Jeśli symbolem przekierowania jest"<tab> są usuwane z linii wejściowych i linii zawierającej ogranicznik końcowy. Jeżeli w wierszu podano więcej niż jeden operator "
Gdy dokument here jest odczytywany z urządzenia końcowego i powłoka jest interaktywna, zapisuje zawartość zmiennej PS2, przetworzonej w sposób opisany w zmiennych powłoki, do standardowego błędu przed odczytaniem każdej linii wejścia, aż do rozpoznania ogranicznika.
Przykłady
Niektóre przykłady jeszcze nie podane.
Cudzysłowy zapobiegają rozszerzaniu parametrów
Bez cudzysłowów:
a=0
cat <<EOF
$a
EOF
Wyjście:
0
Z cytatami:
a=0
cat <<'EOF'
$a
EOF
Lub (brzydki, ale ważny):
a=0
cat <<E"O"F
$a
EOF
Wyjścia:
$a
Myślnik usuwa początek tabs
Bez myślnika:
cat <<EOF
<tab>a
EOF
Gdzie <tab>
jest literalną tabulatorem i można ją wstawić za pomocą Ctrl + V <tab>
Wyjście:
<tab>a
Z myślnikiem:
cat <<-EOF
<tab>a
<tab>EOF
Wyjście:
a
Istnieje to oczywiście po to, abyś mógł wciąć swój cat
jak otaczający kod, który jest łatwiejszy do odczytania i utrzymania. Np.:
if true; then
cat <<-EOF
a
EOF
fi
Niestety, nie działa to dla znaków spacji: POSIX faworyzował tab
wcięcia tutaj. Kurczę.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-25 14:51:36
Używanie tee zamiast cat
Nie do końca jako odpowiedź na pierwotne pytanie, ale i tak chciałem się tym podzielić: miałem potrzebę utworzenia pliku konfiguracyjnego w katalogu, który wymagał praw roota.
W tym przypadku nie działa:
$ sudo cat <<EOF >/etc/somedir/foo.conf
# my config file
foo=bar
EOF
Ponieważ przekierowanie jest obsługiwane poza kontekstem sudo.
Zamiast tego użyłem tego:
$ sudo tee <<EOF /etc/somedir/foo.conf >/dev/null
# my config file
foo=bar
EOF
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-13 12:14:06
Niekoniecznie jest to odpowiedź na pierwotne pytanie, ale dzielenie się wynikami z moich własnych testów. To:
<<test > print.sh
#!/bin/bash
echo \$PWD
echo $PWD
test
Wytworzy ten sam plik co:
cat <<test > print.sh
#!/bin/bash
echo \$PWD
echo $PWD
test
Nie widzę sensu używania komendy cat.Warto zauważyć, że tutaj dokumenty działają również w pętlach bash. Ten przykład pokazuje, jak uzyskać listę kolumn tabeli:
export postgres_db_name='my_db'
export table_name='my_table_name'
# start copy
while read -r c; do test -z "$c" || echo $table_name.$c , ; done < <(cat << EOF | psql -t -q -d $postgres_db_name -v table_name="${table_name:-}"
SELECT column_name
FROM information_schema.columns
WHERE 1=1
AND table_schema = 'public'
AND table_name =:'table_name' ;
EOF
)
# stop copy , now paste straight into the bash shell ...
output:
my_table_name.guid ,
my_table_name.id ,
my_table_name.level ,
my_table_name.seq ,
Lub nawet bez nowej linii
while read -r c; do test -z "$c" || echo $table_name.$c , | perl -ne
's/\n//gm;print' ; done < <(cat << EOF | psql -t -q -d $postgres_db_name -v table_name="${table_name:-}"
SELECT column_name
FROM information_schema.columns
WHERE 1=1
AND table_schema = 'public'
AND table_name =:'table_name' ;
EOF
)
# output: daily_issues.guid ,daily_issues.id ,daily_issues.level ,daily_issues.seq ,daily_issues.prio ,daily_issues.weight ,daily_issues.status ,daily_issues.category ,daily_issues.name ,daily_issues.description ,daily_issues.type ,daily_issues.owner
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-14 15:18:35