Możemy użyć albo, sed
albo awk
całkowicie rozwiązać problem.
Z sed
:
$ sed 's/^.\./0&/' file.txt
Kiedy &
występuje w części zastępującej polecenia podstawienia ( s
), zostanie on rozwinięty do części wiersza wejściowego, która odpowiada części wzorcowej polecenia.
Wyrażenie regularne ^.\.
oznacza „ dopasuj wszystkie linie rozpoczynające się od ( ^
) dowolnego znaku ( .
), po którym następuje dosłowna kropka ( \.
) ”.
Jeśli linia jest 1.02.2017 23:40:00
, wzór będzie pasował i 1.
zostanie zastąpiony przez 01.
na początku linii.
Z awk
:
Opierając się na częściowym awk
kodzie w pytaniu ...
Spowoduje to, jak powiedziano, wydrukowanie drugiego znaku każdego wiersza wprowadzania:
$ awk '{ print substr($0, 2, 1) }' file.txt
Możemy użyć faktu, który substr($0, 2, 1)
zwraca drugi znak i użyć go jako warunku:
$ awk 'substr($0, 2, 1) == "." { ... }' file.txt
Wchodzi w { ... }
to kod $0
, który jest poprzedzany, czyli zawartość bieżącego wiersza, z zerem, jeśli powyższy warunek jest prawdziwy:
$ awk 'substr($0, 2, 1) == "." { $0 = "0" $0 }' file.txt
Następnie musimy tylko upewnić się, że wszystkie linie są wydrukowane:
$ awk 'substr($0, 2, 1) == "." { $0 = "0" $0 } { print }' file.txt
Warunek substr($0, 2, 1) == "."
można oczywiście zmienić również na wyrażenie regularne (używamy dokładnie tego samego wyrażenia, co w sed
rozwiązaniu):
$ awk '/^.\./ { $0 = "0" $0 } { print }' file.txt
Niektórzy ludzie, którzy myślą, że „krótszy jest zawsze lepszy” napisaliby to jako
$ awk '/^.\./ { $0 = "0" $0 } 1' file.txt
(i prawdopodobnie również usunąć większość miejsc: awk '/^.\./{$0="0"$0}1' file.txt
)
sed 's/^.\./0&/' file.txt
. Myślę, że powinieneś to umieścić na początku tej odpowiedzi. Nadal +1.Z sed:
Wzorzec
/^.\./
szuka dowolnego znaku i dosłownej kropki na początku linii^
, a jeśli to pasuje, należys
zamienić ten początek linii na zero, skutecznie dodając zero na początku.Ekspreso sed
s/.\{0\}/0/
jest nieco dziwne, dopasowuje zero lub więcej kopii czegokolwiek i zastępuje zero. Wzorzec będzie oczywiście pasował do każdej pozycji ciągu, ale ponieważs///
zastępuje tylko pierwsze dopasowanie, działa zgodnie z przeznaczeniem. Jednak to ciekawy sposób.Lub z awk, podobne wyrażenie regularne działałoby, aby dopasować linię, ale możemy użyć
substr
:Najpierw sprawdzamy, czy drugi znak jest kropką, a następnie dodajemy zero na początku linii, jeśli tak jest. Ostatni wywołuje domyślną akcję drukowania linii po jakichkolwiek modyfikacjach.
źródło
Powiedziałeś awk i sed, ale wygląda na to, że próbujesz sformatować datę i do tego użyłbym
date
polecenia. Na przykład:wyjdzie
sed
Komenda w środku zmienia okresów, ukośniki dla wejścia dodate -d
. Opcje formatu pozwalają na wydruk w prawie dowolnym formacie. W%m
szczególności wyzeruje miesiąc, co wydaje się, że próbujesz to zrobić.Jak zauważa Kusalananda:
Jeszcze bardziej kompaktowy (data GNU i Bash):
date -f <(tr '.' '/' <dates.in) '+%m.%d.%Y %T'
źródło
date -f <(tr '.' '/' <dates.in) '+%m.%d.%Y %T'
s|\.|/|g
. W przeciwnym razie, jak wspomniano powyżej:Inna strategia niż przedstawiona w innych odpowiedziach: możesz użyć „.” jako separator pól.
Możesz zagrać w golfa, aby:
W przypadku sed istnieje krótsze polecenie, przedstawione w innej (świetnej) odpowiedzi.
źródło
awk -F. '{print ($1<10?0$0:$0)}' file
Z sed może to być
Spowoduje to
^
zakotwiczenie na początku linii, a następnie przechwycenie dowolnego pojedynczego znaku w grupie, a następnie literału.
, a następnie wszystkiego innego. Jeśli dopasujemy, że wydrukujemy a0
, to nasza pierwsza grupa przechwytywania (znak na początku linii), a.
następnie nasza druga grupa przechwytywania (reszta linii)źródło
&
jest twoim przyjacielem. Zobacz przykład Kusalanandy.sed
która może być przydatna w innych sytuacjach, nie tylko ten konkretny problem