Próbuję wykonać operację matematyczną sed
, ale nadal traktuję moje zmienne jako ciągi znaków. Dane wejściowe tego rodzaju:
$ echo 12 | sed 's/[0-9]*/&+3/'
$ 12+3
Chciałbym mieć 15 jako wynik. Muszę wykonać operację i zastąpić jej wynik matematyczny tylko jednym przejściem, ponieważ uruchamiam program jako demon w języku Python i chcę uniknąć fragmentów takich jak przekierowywanie stdout
plików, otwieranie tych plików, wykonywanie operacji, wyodrębnianie wyniku, wykonywanie wymiana. sed
Wydaje mi się, że najlepiej jest wykonywać wszystko w jednym wierszu.
Próbowałem rzutować zarówno dane wejściowe, jak i wyjściowe na różne sposoby
$ echo 12 | sed 's/[0-9]*/int(&+3)/'
$ echo 12 | sed 's/[0-9]*/\int(&+3)/'
$ echo 12 | sed 's/[0-9]*/\int(&+3)/'
ale rezultatem było zawsze wydrukowanie drugiego pola.
sed
matematykiOdpowiedzi:
Jeśli naprawdę chcesz korzystać z sed, to jest taka droga:
Wejście:
Wynik:
Twoim zadaniem, jeśli zdecydujesz się to zaakceptować, jest wdrożenie mnożenia.
źródło
sed
nie jest tutaj najlepszą opcją, nie wykonuje natywnej arytmetyki (zobacz Zwiększ liczbę, jak możesz to zrobić). Możesz to zrobić za pomocąawk
:Najlepszy fragment kodu będzie zależał od dokładnego formatu danych wejściowych i tego, co chcesz / musisz zrobić, jeśli nie jest on numeryczny lub zawiera więcej niż jedną liczbę itp.
Możesz to zrobić tylko z
bash
:lub używając
expr
w podobny sposób.źródło
Próbowałem zaakceptować twoje wyzwanie @Richter, oto co zrobiłem używając części twojego kodu:
Wejście:
Dane wyjściowe: wszystkie prawidłowe wyniki
źródło
perl
pozwala na bardzo podobną konstrukcję dosed
... jedną różnicą jest to, żeperl
można robić bardziej złożone rzeczy ...sed
jest bardzo dobry dla prostych podstacji tekstowychwydajność
źródło
perl -pe 's/[0-9]+/$&+3/e'
po prostu podaj ciąg do kalkulatora
źródło
Naprawdę nie rozumiem, dlaczego ekstremalna złożoność zaakceptowanej odpowiedzi, jedno z poniższych, robi to, co chcesz:
lub
Myślę, że może to wymagać GNU sed, ale nie jestem pewien.
źródło
echo 12+3 | sed -r 's/([0-9]*) *\+ *([0-9]*)/expr \1 + \2/e'
Jeśli zdecydowanie musisz połączyć wyrażenia regularne i operacje arytmetyczne, wybierz język, w którym parametr zastępujący wyrażenie regularne może być funkcją zwrotną.
Perl, Ruby, JavaScript i Python to takie języki:
źródło
Kolejne proste
bash
rozwiązanie, które faktycznie działa w rurze:źródło
Jeśli wmieszasz trochę bashizmu:
Aby wyodrębnić liczbę z tekstu:
Bez sed, po prostu bash:
zastępuje każdą cyfrę
${var//[^0-9]/}
i wykonuje arytmetykę w podwójnych okrągłych parens:$((x+3))
źródło
$((...))
został wprowadzony przez POSIX (bashism is$[...]
).${var//xxx/x}
to kshism również skopiowany przez zsh i bash.sed -r
jest GNUizmemOto rozwiązanie Perla:
Jeśli wolisz zmienić pierwszy zestaw cyfr napotkany w ciągu, możesz użyć:
Jeśli wolisz zmienić wszystkie zestawy cyfr w ciągu, możesz użyć
/g
modyfikatora w następujący sposób:źródło
Chociaż użycie wyrażenia sed jest świetne, ma swoje ograniczenia. Na przykład nie powiedzie się:
Aby przezwyciężyć to ograniczenie, po prostu zwracam się do wbudowanej mocy czystego seda i implementuję następujący sumator dziesiętny o dowolnej długości:
Działa to poprzez implementację modułu sumatora dziesiętnego, który dodaje dwie cyfry wejściowe (A i B), a także Carry Bit i generuje bit Sum i Carry. Pomysł zapożyczono z wersji elektronicznej, w której sumator binarny robi to samo dla liczb binarnych. Wystarczy, że dodamy pętlę do wszystkich cyfr i możemy dodać dowolne liczby długości (ograniczone pamięcią). Poniżej znajduje się sumator w akcji:
Dokładnie w ten sam sposób można zaimplementować binarny (lub dowolny inny podstawowy) sumator. Wszystko, co musisz zrobić, to zastąpić linię rozpoczynającą się
s/$/;000=00001...
od właściwego wzorca podstawienia dla danej bazy. Na przykład:s/$/;000=00001=01010=01011=10100=01101=10110=10111=11/
jest wzorem podstawiania dla binarnego sumatora o dowolnej długości.Możesz dopasować kod udokumentowany na moim githubie .
źródło