sed nie daje mi poprawnej operacji zastępczej dla newline z Mac-różnice między GNU sed i BSD / OSX sed [duplikat]
To pytanie ma już odpowiedź tutaj:
- Zastąp przecinek znakiem nowej linii w sed 12 odpowiedzi
Używam tego odniesienia: sed help: dopasowanie i zastąpienie dosłownego "\n " (nie nowej linii)
I mam plik " test1.txt", który zawiera łańcuch hello\ngoodbye
Używam tego polecenia do wyszukiwania i zamiany "\n " na rzeczywiste znaki nowej linii:
sed -i '' 's/\\n/\n/g' test1.txt
Ale wynik jest: hellongoodbye. zastępuje tylko "\n "przez " n", A nie rzeczywistą nową linię. To samo robi z /t, gdzie zostawia" t", a nie zakładkę.
" jest dla niezdefiniowanego błędu w MAC: http://mpdaugherty.wordpress.com/2010/05/27/difference-with-sed-in-place-editing-on-mac-os-x-vs-linux/
Update :
Próbowałem obu komend, które @hek2mgl "suggested": {]}
sed -i 's/\\n/\n/g' test.txt
# Or:
sed -i'' 's/\\n/\n/g' test.txt
Chociaż mogą pracować z Linuksem, z MAC OS mam następujący błąd:
sed: 1: "test1.txt": undefined label 'est1.txt'
Nie wiem, dlaczego nie mogę tego uruchomić. Z góry dzięki. 2 answers
W przypadku BSD/macOS sed
, aby użyć nowego wiersza zastępczego ciągu wywołania funkcji s
, musisz użyć \
-Escape rzeczywista newline - Sekwencja escape \n
jest nie wspierana tam (w przeciwieństwie do regex część rozmowy).
-
albo : po prostu wstaw rzeczywisty newline:
sed -i '' 's/\\n/\ /g' test1.txt
-
Or : use an ANSI C-quoted string (
$'...'
) do splicingu w newline ($'\n'
; działa wbash
,ksh
, lubzsh
):sed -i '' 's/\\n/\'$'\n''/g' test1.txt
GNU sed
, natomiast rozpoznaje w ciągach zastępczych; Czytaj dalej, aby uzyskać obszerny przegląd różnic między tymi dwiema implementacjami.
Różnice pomiędzy GNU sed
(Linux) a BSD / macOS sed
macOS używa wersji BSD sed
[1], które różni się pod wieloma względami od GNU sed
wersja, która pochodzi z Linux DISTRO.
Ich wspólny mianownik to funkcjonalność określona przez POSIX : zobacz spec POSIX sed
.
Najbardziej przenośnym podejściem jest używanie tylko funkcji POSIX , które jednak ogranicza funkcjonalność :
- w szczególności, POSIX określa wsparcie tylko dla podstawowe wyrażenia regularne, które mają wiele ograniczeń (np. brak wsparcia dla
|
(alternacja) w ogóle, brak bezpośredniego wsparcia dla+
i?
) i różne wymagania specjalne.- Zastrzeżenie: GNU
sed
(bez-r
), czy obsługuje\|
,\+
i\?
, które nie są zgodne ze standardem POSIX; użyj--posix
, aby wyłączyć (patrz poniżej).
- Zastrzeżenie: GNU
-
aby używać tylko funkcji POSIX :
- (obie wersje): należy używać tylko opcji
-n
i-e
(w szczególności nie należy używać-E
lub-r
do włączania obsługi rozszerzonych wyrażeń regularnych) - GNU
sed
: Dodaj opcjÄ ™--posix
aby zapewniÄ ‡ funkcjonalnoĹ "Ä ‡ tylko w standardzie POSIX (nie jest to absolutnie potrzebne, ale bez niej moĹźna byĹ' oby nieumyślnie uĺźywaä ‡ funkcji innych niż POSIX, nie zwracajÄ ... c uwagi; zastrzeżenie:--posix
nie jest to zgodne z POSIX) - używanie tylko funkcji POSIX oznacza surowsze wymagania formatowania (rezygnacja z wielu udogodnień dostępnych w GNU
sed
):- sekwencje znaków sterujących, takie jak
\n
i\t
, na ogół nie są obsługiwane. - etykiety i polecenia rozgałęziające (np.,
b
) musi następować rzeczywista nowa linia lub kontynuacja poprzez oddzielną opcję-e
. - zobacz poniżej szczegóły.
- sekwencje znaków sterujących, takie jak
- (obie wersje): należy używać tylko opcji
Jednak obie wersje implementacja rozszerzeń do standardu POSIX:
-
czym rozszerzenia implementują różnią się (GNU
sed
implementuje więcej). - nawet te rozszerzenia one oba implementują częściowo różnią się składnią.
Jeśli potrzebujesz wspierać obie platformy (omówienie różnic):
-
Niekompatybilne funkcje:
- użycie na
-i
opcja bez argument (in-place update without backup) jest niezgodny:- BSD
sed
: musi używać-i ''
- GNU
sed
: musi używać tylko-i
(odpowiednik:-i''
) - używanie-i ''
nie działa.
- BSD
-
-i
sensownie włącza per-input-file numeracja linii w GNUsed
i najnowsze wersje BSDsed
(np. na FreeBSD 10), ale czy Nie na macOS od 10.12.
Należy pamiętać, że w przypadku braku-i
wszystkie wersje numerują linie łącznie pomiędzy Plikami wejściowymi. - jeśli ostatnia linia wejściowa ma nie ma końcową nową linię (i jest drukowana):
- BSD
sed
: zawsze dodaje nową linię na wyjściu, nawet jeśli linia wejściowa nie kończy się na niej. - GNU
sed
: zachowuje status wątku końcowego-newline , tzn. dopisuje nową linię tylko wtedy, gdy linia wejściowa kończy się na jednej.
- BSD
- użycie na
-
wspólne cechy:
- jeśli ograniczysz swoje skrypty
sed
do tego, co obsługuje BSDsed
, będą one również działać w GNUsed
- z zauważalnym wyjątkiem używania specyficznych dla platformy rozszerzonych funkcji regex z-E
. Oczywiście zrezygnujesz także z rozszerzeń, które są specyficzne dla wersji GNU. Zobacz następny sekcja.
- jeśli ograniczysz swoje skrypty
W 2004 roku, w ramach projektu, w ramach projektu, w ramach projektu, stworzono nową wersję systemu operacyjnego dla systemu operacyjnego Linux, która miała zostać wdrożona w 2006 roku.]}
zauważ, że używam skrótów macOS i Linux odpowiednio dla wersji BSD i GNU Uwaga: z wyjątkiem sytuacji, gdy używane są flagi Dla potężniejszych wyrażenia regularne, użyj Sekwencje ucieczki znaków sterujących, takie jak W ciągach zastępczych używanych z poleceniem Ditto dla argumentów tekstowych do GNU Funkcje GNU, których przegapisz, jeśli potrzebujesz wspierać obie platformy: Różne opcje dopasowania regex i substytucji (zarówno we wzorcach do wyboru linii, jak i pierwszego argumentu do funkcji Sekwencje ucieczki Sekwencje specjalne związane z podstawieniem, takie jak Sekwencje Escape Control-character: oprócz Rozszerzenia adresów , takie jak [1] wersja macOS [2] cytowany ciąg znaków sed
, ponieważ są to wersje zapasowe na każdej platformie. Można jednak zainstalować GNU sed
na macOS, na przykład za pomocą Homebrew z brew install gnu-sed
.
-r
i -E
(rozszerzone wyrażenia regularne), poniższe instrukcje stanowią zapis zgodny z POSIX sed
Skrypty.
Zastrzeżenie : nie zakładaj, że \|
, \+
i \?
są obsługiwane: podczas gdy GNU sed
je obsługuje (chyba że użyto --posix
), BSD sed
nie - te funkcje nie są zgodne z POSIX.
While \+
oraz \?
można emulować w sposób zgodny z POSIX:\{1,\}
na \+
,\{0,1\}
na \?
,\|
(alternation) cannot, niestety.-E
(zamiast -r
) do obsługi EREs ( rozszerzone wyrażenia regularne) (GNU sed
nie dokumentuje -E
, ale działa tam jako alias -r
; nowsza wersja BSD sed
, taka jak na FreeBSD 10, teraz również obsługuje -r
, ale wersja macOS od 10.10 nie nie ).
Zastrzeżenie : mimo że użycie -r
/ -E
oznacza, że Twoje polecenie jest z definicji , a nie Zgodny z POSIX, musisz jednak ograniczyć się do POSIX EREs (rozszerzone wyrażenia regularne). Niestety, oznacza to, że nie będziesz w stanie użyć kilku użytecznych konstrukcji, w szczególności: [176]}
\<
na Linuksie, [[:<]]
na OS X).s
function calls), ponieważ BSD sed
nie obsługuje ich w Extended regexes (ale, co ciekawe, robi to w basic , gdzie są wymagane POSIX).\n
i \t
:
s
), Załóżmy, że tylko \n
jest rozpoznawana jako sekwencja escape (rzadko używany, ponieważ przestrzeń wzorca jest zwykle pojedynczą linią (bez kończenia \n
), ale nie wewnątrz klasy znaków, tak że np. [^\n]
nie działa; (jeśli wejście nie zawiera znaków sterujących. inne niż \t
, można emulować [^\n]
za pomocą [[:print:][:blank:]]
; w przeciwnym razie znaki sterujące splice. w as literały[2]) - zazwyczaj, zawierać znaki kontrolne jako literały , albo poprzez spliced-in ANSI C-cytowane ciągi (np., $'\t'
) w powłokach, które go obsługują (bash,
ksh, zsh
), lub poprzez zastępowanie poleceń za pomocą printf
(np., "$(printf '\t')"
).
sed 's/\t/-/' <<<$'a\tb' # -> 'a-b'
sed 's/'$'\t''/-/' <<<$'a\tb' # ANSI C-quoted string
sed 's/'"$(printf '\t')"'/-/' <<<$'a\tb' # command subst. with printf
s
, zakładają, że nie są obsługiwane żadne sekwencje ucieczki znaków sterujących, więc ponownie dołączają znaki sterujące. jako literały , jak wyżej.
sed 's/-/\t/' <<<$'a-b' # -> 'a<tab>b'
sed 's/-/'$'\t''/' <<<'a-b'
sed 's/-/'"$(printf '\t')"'/' <<<'a-b'
i
And a
functions: nie używaj sekwencji znaków sterujących - patrz poniżej.b
i t
musi być poprzedzone przez literal newline lub spliced-in $'\n'
. Alternatywnie, użyj wielu opcji -e
i zakończ każde prawo po nazwie etykiety.
sed -n '/a/ bLBL; d; :LBL p' <<<$'a\nb' # -> 'a'
sed -n '/a/ bLBL
d; :LBL
p' <<<$'a\nb'
$\n
instancje):sed -n '/a/ bLBL'$'\n''d; :LBL'$'\n''p' <<<$'a\nb'
-e
opcje):sed -n -e '/a/ bLBL' -e 'd; :LBL' -e 'p' <<<$'a\nb'
i
i a
do wstawiania / dodawania tekstu: po nazwie funkcji przez \
, a następnie przez literal newline lub spliced-in $'\n'
przed podaniem argumentu tekstowego.
sed '1 i new first line' <<<$'a\nb' # -> 'new first line<nl>a<nl>b'
sed -e '1 i\'$'\n''new first line' <<<$'a\nb'
-e
argument tekstowy jest niewytłumaczalny nie newline-zakończone na wyjściu w macOS (błąd?).\n
i \t
w argumencie tekstowym, ponieważ są one obsługiwane tylko w Linuksie.\
-unikaj ich.-e
(jest to ogólny wymóg, który dotyczy wszystkich wersji).{...}
), należy również zakończyć funkcję last , przed zamknięciem }
, z ;
.
sed -n '1 {p;q}' <<<$'a\nb' # -> 'a'
sed -n '1 {p;q;}' <<<$'a\nb'
sed
- Cechy szczególne brakuje w BSD sed
razem:
s
):
I
dla dopasowania regex niewrażliwego na wielkość liter (niesamowicie, BSD sed
w ogóle tego nie obsługuje).M
opcja dopasowania wielowierszowego (gdzie ^
/ $
dopasuj początek / koniec każdej linii ) s
Zobacz https://www.gnu.org/software/sed/manual/sed.html#The-_0022s_0022-Command
\u
w argumencie zastępczym funkcji s///
, które pozwalają manipulacja substratem , w granicach; np. sed 's/^./\u&/' <<<'dog' # -> 'Dog'
- patrz http://www.gnu.org/software/sed/manual/sed.html#The-_0022s_0022-Command\n
, \t
, ..., ucieczki oparte na punktach kodowych; na przykład wszystkie następujące ucieczki (hex., ósemkowe, dziesiętne) reprezentują pojedynczy cytat ('
): \x27
, \o047
, \d039
- Zobacz też https://www.gnu.org/software/sed/manual/sed.html#Escapesfirst~step
, aby dopasować każdy krok-TH linii, addr, +N
, aby dopasować N linii następujących po addr
,... - zobacz http://www.gnu.org/software/sed/manual/sed.html#Addresses
sed
jest starsza niż wersja na innych systemach podobnych do BSD, takich jak FreeBSD i PC-BSD. Niestety, oznacza to, że nie można zakładać, że funkcje, które działają w FreeBSD, na przykład, będą działać [to samo] na macOS.$'\001\002\003\004\005\006\007\010\011\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037\177'
ANSI C zawiera wszystkie znaki kontrolne ASCII oprócz \n
(i NUL), więc można go używać w połączeniu z [:print:]
dla dość solidnej emulacji [^\n]
:'[[:print:]'$'\001\002\003\004\005\006\007\010\011\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037\177'']
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-09-06 03:32:03
To może wydawać się trochę dziwne, ale spróbuj:
sed -i '' 's/\\n/\
/g' test1.txt
Tj. użyj rzeczywistej nowej linii zamiast \n
.
Wyjaśnienie jest takie, że masz dziwne sed
!
Szczegółowe informacje można znaleźć w podręczniku Mac sed: https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man1/sed.1.html
W opisie komendy s
jest napisane:
A line can be split by substituting a newline character into it. To specify
a newline character in the replacement string, precede it with a backslash.
Również w opisie opcji -i
jest napisane, że rozszerzenie nie jest opcjonalne, i że jeśli nie chcesz, musisz podać pusty argument. Więc wszystko ma sens w końcu!
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
2014-06-18 01:01:07