Jak usunąć pierwszy dwukropek „:” ze znacznika czasu?

10

Jestem nowy w programowaniu !!

Czy ktoś może pomóc usunąć :pierwszą pozycję znacznika czasu::29.06.2019 23:03:17

Obecnie próbuję to zrobić za pomocą poleceń awk / cut, jak pokazano poniżej:

TDS="$(grep 'Logfile started' process.log |  awk '{print $3,$4}' | cut -d: -f2)"
echo "$TDS"


29.06.2019 23

A wynik nie jest tym, czego chciałem! Chcę to wydrukować jako 29.06.2019 23:03:17.

Manoj Kumar
źródło

Odpowiedzi:

14

Aby odciąć pierwszą postać, możesz również użyć cut -c:

$ echo ":29.06.2019 23:03:17" | cut -c 2-
29.06.2019 23:03:17
pLumo
źródło
11

Posługiwać się

cut -d: -f2-

zamiast

cut -d: -f2

aby uzyskać cokolwiek z drugiego pola do końca linii:

TDS="$(grep 'Logfile started' process.log |  awk '{print $3,$4}' | cut -d: -f2-)"
echo "$TDS"
Florian Diesch
źródło
8

awkto fajne narzędzie, dzięki któremu możesz rozwiązywać bardzo złożone zadania. Ale w przypadku twojego pytania wolę trzymać podstawowe możliwości bash.

Aby to łatwo usunąć podstąpienie, zrobiłbym następujące czynności:

zehe="Logfile started :29.06.2019 23:03:17"
echo "${zehe#*:}"

to wydrukuje:

29.06.2019 23:03:17

Kiedy byłem na twoim miejscu i zacząłem uczyć się programowania i bash, nauczyłem się wielu z tego Podręcznika:

ABS - Advanced Bash-Scripting Guide

Więcej przykładów i interesujących informacji na temat twojego problemu można znaleźć tutaj , poszukaj „Usuwanie podciągów”.

Hannes Morgenstern
źródło
3
+1 to! Ponieważ pytanie jest oznaczone jako „bash”, należy rozważyć preferowanie wielkich (choć często dość niejasnych) możliwości manipulowania łańcuchami, które są znacznie szybsze niż ładowanie narzędzi zewnętrznych.
rexkogitans 17.07.19
2
@rexkogitans, ponieważ już wywołujemy grep lub awk w celu parsowania pliku, bash nie będzie szybszy. W rzeczywistości za każdym razem, gdy trzeba przeanalizować plik, bash pliku będzie działał powoli. Wszystkie pociski są wolne, a uderzenie wolniejsze niż większość. To powiedziawszy, możliwości manipulacji ciągiem powłoki są rzeczywiście często najlepszym podejściem, ale tylko wtedy, gdy masz już dane wejściowe jako zmienną.
terdon
8

Oto sedrozwiązanie:

$ echo ':29.06.2019 23:03:17' | sed 's/^://'
29.06.2019 23:03:17

Polecenie sed 's/^://'zastępuje sznak dwukropka :na początku ^każdego wiersza pustym ciągiem //.

Oto trudne awkrozwiązanie, w którym zmieniamy separator pól na ^:opisany powyżej i wyprowadzamy drugie pole (każdej linii):

$ echo ':29.06.2019 23:03:17' | awk -F'^:' '{print $2}'
29.06.2019 23:03:17

Zadanie można wykonać również za pomocą grep( objaśnienia ), prawdopodobnie jest to najszybsze rozwiązanie dla dużej ilości danych:

$ echo 'Logfile started :29.06.2019 23:03:17' | grep -Po '^Logfile started :\K.*'
29.06.2019 23:03:17

Lub przetworz plik bezpośrednio za pomocą następującego polecenia, w którym ograniczenie ^zostanie usunięte:

grep -Po 'Logfile started :\K.*' process.log

Powyższe można osiągnąć również poprzez sedprzechwytywanie grup ()->\1:

sed -nr 's/^.*Logfile started :(.*)$/\1/p' process.log

Gdzie wyrażenie ^.*<something>.*$pasuje do całej linii, która zawiera <something>. Polecenie s/old/new/zastąpi ten wiersz treścią pierwszej grupy przechwytywania (wyrażenie w nawiasach może być bardziej konkretne). Opcja -rwłącza rozszerzone wyrażenia regularne. Opcja -npominie normalne wyjście, seda na końcu polecenie pwydrukuje dopasowania.

pa4080
źródło
Nigdy nie wiedziałem, że awkmoże istnieć wieloznakowa FS ze znakami o specjalnym znaczeniu! Nauczyłem się dzisiaj.
Floris,
6

Ponieważ już to przetwarzasz awk, możesz równie dobrze zrobić całą rzecz bezpośrednio:

$ echo "foo bar :29.06.2019 23:03:17" |  awk '{sub(/^:/,"",$3); print $3,$4}' 
29.06.2019 23:03:17

W subogóle Format polecenia jest sub(/REGEX/, REPLACEMENT, TARGET)i będzie wymienić wszystkie mecze do wyrażenia regularnego REGEXz ciąg REPLACEMENTw ciągu wejściowego TARGET. Tutaj zastępujemy pierwszy :( ^czyli „początek”) z trzeciego pola ( $3) niczym.

Oczywiście, jeśli robisz to w awk, możesz równie dobrze zrobić wszystko w awk i zrobić wszystko za jednym razem:

$ echo "Logfile started :29.06.2019 23:03:17" | 
    awk '/Logfile started/{sub(/^:/,"",$3); print $3,$4}' 
29.06.2019 23:03:17

Lub w twoim przypadku:

TDS="$(awk '/Logfile started/{sub(/^:/,"",$3); print $3,$4}' process.log)"
echo "$TDS"
terdon
źródło
0

Kolejne rozwiązanie bash:

$ echo "Logfile started :29.06.2019 23:03:17" | xargs bash -c 'echo "${2#*:} $3"'
29.06.2019 23:03:17
  • Używa to potoku zamiast przypisania zmiennej pośredniej.
  • Polecenie xargskonwertuje stdin(standardowe wejście) na parametry pozycyjne dla bashpolecenia.
  • Wymień echosię tail -n1 /path/to/reportfile.txt.
WinEunuuchs2Unix
źródło