Mam sytuację, w której chcę, aby skrypt bash zastąpił całą linię w pliku. Numer wiersza jest zawsze taki sam, więc może to być zmienna zakodowana na stałe.
Nie próbuję zamienić jakiegoś podciągu w tym wierszu, po prostu chcę całkowicie zastąpić ten wiersz nowym wierszem.
Czy są do tego jakieś metody basha (lub coś prostego, które można wrzucić do skryptu .sh).
sed: -e expression #1, char 26: unknown option to ``s'
a moja linia jest:sed -i '7s/.*/<param-value>http://localhost:8080/ASDF/services/REWS.REWSHttpSoap12Endpoint/</param-value>/' $TCE_SVN_HOME\trunk\tce\EWC\WebContent\WEB-INF\web.xml
. Dowolny pomysł?/
w tekście zastępczym byłby interpretowany jako zamykający ukośniks
polecenia, chyba że jest to znak ucieczki (\/
). Najłatwiej jednak jest wybrać inny, nieużywany znak jako separator. Na przykładsed -i '7s{.*}{<param-value>http://...}' $TCE_SVN_HOME/trunk...
.s
określa separator. Tak więc, aby zmienić polecenie, aby użyć na przykład polecenia#
, wyglądałoby to tak:sed -i '7s#.*#<param-value>http://localhost:8080/ASDF/services/REWS.REWSHttpSoap12Endpoint/</param-value>#'
-e
if-i
; tak więc poprawne polecenie to:sed -e 'Ns/.*/replacement-line/' -i '' file.txt
Właściwie użyłem tego skryptu do zastąpienia linii kodu w pliku cron na serwerach UNIX naszej firmy. Wykonaliśmy to jako normalny skrypt powłoki i nie mieliśmy żadnych problemów:
Nie chodzi o numer linii, ale możesz łatwo przełączyć się na system oparty na numerach linii, umieszczając numer linii przed
s/
znakiem i zastępując go symbolem wieloznacznymthe_original_line
.źródło
sed -e "s/.../.../" /dir/file > /dir/temp_file
sed -e "s/.../.../" /dir/file > /dir/file
Załóżmy, że chcesz zastąpić wiersz 4 tekstem „inny”. Możesz używać AWK w następujący sposób:
AWK traktuje dane wejściowe jako „rekordy” podzielone na „pola”. Domyślnie jeden wiersz to jeden rekord.
NR
to liczba wyświetlonych rekordów.$0
reprezentuje bieżący pełny rekord (gdzie$1
jest pierwszym polem z rekordu i tak dalej; domyślnie pola są słowami z wiersza).Tak więc, jeśli bieżący numer wiersza to 4, wypisuje łańcuch „inny”, ale w przeciwnym razie wypisuje wiersz bez zmian.
W AWK kod programu zawarty w jest
{ }
uruchamiany raz na każdym rekordzie wejściowym.Musisz cytować program AWK w pojedynczych cudzysłowach, aby powłoka nie próbowała interpretować rzeczy takich jak
$0
.EDYCJA: Krótszy i bardziej elegancki program AWK od @chepner w komentarzach poniżej:
Tylko dla rekordu (tj. Linii) numer 4, zastąp cały rekord ciągiem „różne”. Następnie wydrukuj rekord dla każdego rekordu wejściowego.
Najwyraźniej moje umiejętności AWK są zardzewiałe! Dziękuję @chepner.
EDYCJA: i zobacz także jeszcze krótszą wersję od @Dennis Williamson:
Jak to działa, wyjaśniono w komentarzach:
1
zawsze zwraca wartość true, więc powiązany blok kodu zawsze działa. Ale nie ma powiązanego bloku kodu, co oznacza, że AWK wykonuje swoją domyślną akcję, po prostu wypisuje całą linię. AWK został zaprojektowany, aby zezwalać na takie zwięzłe programy.źródło
awk 'NR==4 {$0="different"} { print }' input_file.txt
.awk 'NR==4 {$0="different"}1' input_file.txt
1
? (Uwaga: przetestowałem to i rzeczywiście działa! Po prostu nie rozumiem jak.)Biorąc pod uwagę ten plik testowy (test.txt)
poniższe polecenie zamieni pierwszą linię na „tekst nowego wiersza”
Wynik:
więcej informacji można znaleźć tutaj
http://www.thegeekstuff.com/2009/11/unix-sed-tutorial-append-insert-replace-and-count-file-lines/
źródło
sed '1 cnewline text' test.txt
zrobiłby to również.w bash zamień N, M na numery linii, a xxx yyy na to, co chcesz
EDYTOWAĆ
W rzeczywistości w tym rozwiązaniu występują problemy ze znakami „\ 0” „\ t” i „\”
"\ t", można rozwiązać, umieszczając IFS = przed przeczytaniem: "\" na końcu linii z -r
ale dla "\ 0" zmienna jest obcięta, nie ma rozwiązania w czystym bash: Przypisz ciąg zawierający znak null (\ 0) do zmiennej w Bash Ale w normalnym pliku tekstowym nie ma znaku nul \ 0
Perl byłby lepszym wyborem
źródło
źródło
Doskonała odpowiedź od Chepnera. Działa dla mnie w bash Shell.
tutaj
index
- Line nonewLine
- nowy ciąg linii, który chcemy zamienić.Podobnie poniższy kod służy do odczytu konkretnej linii w pliku. Nie wpłynie to na rzeczywisty plik.
tutaj
!d
- usunie linie inne niż linia nr.$index
Otrzymamy wynik jako ciąg linii o numerze nie$index
w pliku.źródło
${newline}
?Na komputerze Mac, którego użyłem
źródło
Możesz nawet przekazać parametry do polecenia sed:
test.sh
orignial output.dat:
Wykonanie ./test.sh daje nowy output.dat
źródło
line=5; sed -i "${line}s/.*/replaced by '$i'!/" output.dat