Mam problem z obniżeniem składni sed, aby dodać różną liczbę zer wiodących do numerycznego schematu organizacyjnego. Wyglądają na ciągi, na których operuję
1.1.1.1,Some Text Here
wykorzystując składnię sed
sed -r ":r;s/\b[0-9]{1,$((1))}\b/0&/g;tr"
Jestem w stanie uzyskać odpowiedź
01.01.01.01,Some Text Here
Jednak to, czego szukam, to wypełnienie zera do 2 cyfr w polach 2 i 3 i 3 cyfr w polu 4, aby wszystkie elementy miały standardową długość w [0-9]. [0-9] { 2}. [0–9] {2}. [0–9] {3}
1.01.01.001,Some Text Here
Przez całe życie nie potrafię nawet wymyślić, jak zmodyfikować granicę, aby uwzględnić parametry niezbędne do przyciągania tylko cyfr po kropce. Myślę, że ma to coś wspólnego z użyciem \ b, które, jak rozumiem, dopasowuje zero znaków na granicy słów, ale nie rozumiem, dlaczego moje próby dodania kropki do dopasowania kończą się następująco:
sed -r ":r;s/\.\b[0-9]{1,$((1))}\b/0&/g;tr"
sed -r ":r;s/\b\.[0-9]{1,$((1))}\b/0&/g;tr"
Both cause the statement to hang
sed -r ":r;s/\b[0-9]\.{1,$((1))}\b/0&/g;tr"
sed -r ":r;s/\b[0-9]{1,$((1))}\.\b/0&/g;tr"
sed -r ":r;s/\b[0-9]{1,$((1))}\b\./0&/g;tr"
cause the statement to output:
1.01.01.1,Some Text Here
Ponadto oczekuję, że będę mieć dodatkowe problemy, jeśli instrukcja zawiera tekst taki jak:
1.1.1.1,Some Number 1 Here
Jest to przesądzony wniosek, że muszę naprawdę nauczyć się sed i wszystkich jego zawiłości. Pracuję nad tym, ale spodziewam się, że to konkretne stwierdzenie będzie nadal przysparzało mi kłopotów. Każda pomoc byłaby bardzo mile widziana.
EDYCJA: Wymyśliłem sposób ... To stwierdzenie wydaje się robić to, czego szukam, ale musi być bardziej elegancki sposób na zrobienie tego.
sed -r ':r;s/\b[0-9]{1,1}\.\b/0&/;tr;:i;s/\b[0-9]{1,2},\b/0&/;ti;s/.//'
Również syntaktycznie spowoduje to problemy, jeśli w tekście pojawi się podobny format liczb ... podobny do:
1.1.1.1,Some Text Referring to Document XXX Heading 1.2.3
W takim przypadku spowoduje to:
1.01.01.001,Some Text Referring to Document XXX Heading 01.02.03
Rozwiązany Dziękuję wszystkim za pomoc tutaj. Początkowo rozwiązałem problem z odpowiedzią, którą zaakceptowałem poniżej. Wydaje mi się, że przeniosłem rozwiązanie do Pythona jako część większego rozwiązania wykorzystującego poniższy sposób:
def getPaddedKey(line):
keyparts = line[0].split(".")
keyparts = map(lambda x: x.rjust(5, '0'), keyparts)
return '.'.join(keyparts)
s=sorted(reader, key=getPaddedKey)
źródło
sed -r ':r;s/\b[0-9]{1,1}\.\b/0&/;tr;:i;s/\b[0-9]{1,2},\b/0&/;ti;s/.//'
chciałbym jednak wiedzieć, czy istnieje bardziej eleganckie podejście.printf
(lubprintf
połączenie w ramach Awk) może być prostsze.Odpowiedzi:
Stosowanie:
leading_zero.sh input.txt
Wyjaśnienie:
input.txt
output.txt
źródło
perl
wersja nie usuwa ukośników odwrotnych.bash sobie z tym poradzi. Będzie jednak dużo wolniejszy niż Perl:
źródło
printf
sensownego narzędzia. (Awk maprintf
również i jest lepiej zaprojektowany niżbash
do przetwarzania tekstu.) Zobacz także Dlaczego używanie pętli powłoki do przetwarzania tekstu jest uważane za złą praktykę?Nie poprosiłeś konkretnie o
perl
rozwiązanie, ale i tak jest jedno. Osobiście uważam, że jest to trochę łatwiejsze do odczytania, zwłaszcza gdy jest podzielone na kilka wierszy.Po pierwsze, jest to jedna linijka:
Jego wyniki:
A oto
perl
skrypt podzielony i skomentowany (-n
flaga umieszcza niejawnąwhile read; do ... done
pętlę wokół kodu):źródło
awk
działałby - przy użyciu tej samej zasadyprintf
Oto jedno z możliwych podejść:
sed -E 's/([0-9]*\.)/0\1/g;s/.//;s/([0-9]*,)/00\1/'
Przykłady
Pracuj także z tym ciągiem:
... i ten ciąg:
źródło
Wyjaśnienie:
Zastosowana metoda polega na tym, by spojrzeć na dzielnice numeryczne i na tej podstawie podjąć działania. Tak więc, druga i trzecia liczba widzą kropkę po obu stronach, podczas gdy czwarta cyfra widzi kropkę po jej lewej stronie i przecinek po prawej.
1 $ jest ustawiany, gdy wyrażenie regularne przyjmuje ścieżkę 2-ej lub 3-tej liczby i odpowiednio dopełnienie precyzyjne wynosi 2. OTOH, dla 4-tej liczby wypełnienie wynosi 3.
% cat file.txt
Wyniki:
źródło