Использование sed для поиска, преобразования и замены строк - PullRequest
1 голос
/ 03 января 2011

Я не слишком разбираюсь в сценариях bash и пытаюсь разработать сценарий bash для следующих операций:

  • У меня много файлов .txt в одной директории.
  • Каждый файл .txt имеет следующую структуру:

file1.txt:
<имя> первая операция
<Операция> 21 </ операция>
<Время_запуск> 1292435633 </ время_запуск>
1292435640

<имя> вторая операция
<Операция> 21 </ операция>
<Время_запуск> 1292435646 </ время_запуск>
1292435650

  • Я хочу выполнить поиск в каждой строке и преобразовать ее в стандартный формат даты / времени (не отметка времени unix), но сохранить структуру 2010-12-15 22:52 , для пример. Это может быть функцией поиска / замены, используя sed? Я думаю, я мог бы использовать эти функции, которые я нашел: date --utc --date "1970-01-01 $ 1 sec" "+% Y-% m-% d% T"

  • Я хочу сделать то же самое с тегом .

  • Я должен сделать это для всех * .txt файлов в каталоге.

Я пытался использовать sed, но с нежелательными результатами. Как я уже сказал, я не очень разбираюсь в скриптах bash, поэтому любая помощь будет признательна.

Спасибо за помощь!

Привет

Ответы [ 2 ]

1 голос
/ 03 января 2011

sed не может выполнять преобразование даты; вместо этого я бы рекомендовал вам использовать более подходящий инструмент, такой как awk:

echo '<StartTime>1292435633</StartTime>' | awk '{
    match($0,/[0-9]+/);
    t = strftime("%F %T",substr($0,RSTART,RLENGTH),1);
    sub(/[0-9]+/,t)
} 
{print}'

Если ваши входные файлы имеют один тег на строку, как в примере с вашей структурой, он должен работать без сбоев.

Если вам нужно повторить операцию для каждого файла .txt, просто используйте оболочку для:

for file in *.txt; do
    awk '/^<[^>]*Time>/{
        match($0,/[0-9]+/);
        t = strftime("%F %T",substr($0,RSTART,RLENGTH),1);
        sub(/[0-9]+/,t)
    } 1' "$file" >"$file.new"
    # mv "$file.new" "$file"
done

По сравнению с предыдущим кодом я сделал два небольших изменения:

  • добавлено условие / ^ <[^>] * Время> /, которое проверяет, начинается ли текущая строка с или
  • преобразовано {print} в более короткое '1'

Если файлы, заканчивающиеся на .new, содержат ожидаемый результат, вы можете раскомментировать строку, содержащую mv.

0 голосов
/ 23 июня 2014

Использование grep:

while read line;do
    if [[ $line == *"<StartTime>"* || $line == *"<EndTime>"* ]];then
        n=$(echo $line | grep -Po '(?<=(>)).*(?=<)')
        line=${line/$n/$(date -d @$n)}
    fi

    echo $line >> file1.new.txt
done < file1.txt

$ cat file1.new.txt 
<name>first operation</name>
<operation>21</operation>
<StartTime>Wed Dec 15 18:53:53 CET 2010</StartTime>
<EndTime>Wed Dec 15 18:54:00 CET 2010</EndTime>

<name>second operation</name>
<operation>21</operation>
<StartTime>Wed Dec 15 18:54:06 CET 2010</StartTime>
<EndTime>Wed Dec 15 18:54:10 CET 2010</EndTime>
...