Нулевое заполнение до 2 цифр с помощью sed


19

Входные данные:

201103 1 /mnt/hdd/PUB/SOMETHING
201102 7 /mnt/hdd/PUB/SOMETH ING
201103 11 /mnt/hdd/PUB/SO METHING
201104 3 /mnt/hdd/PUB/SOMET HING
201106 1 /mnt/hdd/PUB/SOMETHI NG

Желаемый вывод:

201103 01 /mnt/hdd/PUB/SOMETHING
201102 07 /mnt/hdd/PUB/SOMETH ING
201103 11 /mnt/hdd/PUB/SO METHING
201104 03 /mnt/hdd/PUB/SOMET HING
201106 01 /mnt/hdd/PUB/SOMETHI NG

Как я могу добавить, 0если есть только одна цифра, например, 1в части «день»? Мне нужен этот формат даты: ГГГГММ ДД.

Ответы:


13
$ sed 's/\<[0-9]\>/0&/' ./infile
201103 01 /mnt/hdd/PUB/SOMETHING
201102 07 /mnt/hdd/PUB/SOMETH ING
201103 11 /mnt/hdd/PUB/SO METHING
201104 03 /mnt/hdd/PUB/SOMET HING
201106 01 /mnt/hdd/PUB/SOMETHI NG

Можете ли вы объяснить, как это работает? Это первый раз, когда я смотрю на \<[0-9]\>конструкцию, которая, как мне кажется, отвечает за сопоставление однозначных цифр, но не уверена, как называется эта конструкция. Благодарю.
Саске

2
\ <означает: начало слова ... ... [0-9] означает одну цифру от 0 до 9 ... \> означает: конец слова ... слово: токен, разделенный пробелом (или начинается / заканчивается в начале / конце строки, для \ <и \> соответственно) ... PS. Я только что попробовал знаки препинания .. они также являются разделителями.
Peter.O

1
Вы также можете сделать это без захвата скобок: &в строке замены будет использоваться соответствующий LHS -sed 's/\<[0-9]\>/0&/'
glenn jackman

О, не знал, что <>это граница слова в синтаксисе регулярных выражений оболочки. Если подумать, даже `sed 's / \ b [0-9] \ b / 0 & /' также работает. Спасибо вам обоим. :)
Саске

@sasuke: <>это особенность расширенного регулярного выражения (а не оболочки) как такового ... в зависимости от того, какую версию и какие опции вы используете, sedи shellможет использовать как расширенное, так и стандартное регулярное выражение ... стандартное регулярное выражение\<\>
Питер. O


2

Вот (не sed) способ использовать bash с расширенным регулярным выражением .
Этот метод позволяет области видимости выполнять более сложную обработку отдельных строк. (т.е. больше, чем просто подстановка регулярных выражений)

while IFS= read -r line ; do
    if [[ "$line" =~ ^(.+\ )([0-9]\ .+)$ ]]  
    then echo "${BASH_REMATCH[1]}0${BASH_REMATCH[2]}" 
    else echo "$line"
    fi
done <<EOF
201103 1 /mnt/hdd/PUB/SOMETHING
201102 7 /mnt/hdd/PUB/SOMETH ING
201103 11 /mnt/hdd/PUB/SO METHING
201104 3 /mnt/hdd/PUB/SOMET HING
201106 1 /mnt/hdd/PUB/SOMETHI NG
EOF

выход:

201103 01 /mnt/hdd/PUB/SOMETHING
201102 07 /mnt/hdd/PUB/SOMETH ING
201103 11 /mnt/hdd/PUB/SO METHING
201104 03 /mnt/hdd/PUB/SOMET HING
201106 01 /mnt/hdd/PUB/SOMETHI NG

1

Я бы сделал что-то вроде этого:

sed -E 's/ ([0-9]) / 0\1 /' ./input

Это захватывает одинокие числа, удаляет их из пробелов с группой ' ([0-9]) ', затем помещает их обратно с 0 и пробелами ' 0\1 '.

-EОпция позволяет для современных RegEx выражений на OSX (так что вам не придется использовать "\"так часто), -rделает то же самое на Линукс системах я проверил.


Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.