сед

сед

У меня есть такой файл:

171023 03014426 1234 XXXX XXXXXXXX
error code: 123, pc=546, call=0,
171023 03110749 1234 XXXX XXXXXXXX
error code: 123, pc=546, call=0,

Мне нужно сохранить строки с меткой времени, т. е. 171023 03014426 1234 XXXX XXXXXXXXи сохранить error code: 123из других строк, т. е. от начала строки до запятой, и записать изменения в тот же файл.

Выход:

171023 03014426 1234 XXXX XXXXXXXX
error code: 123
171023 03110749 1234 XXXX XXXXXXXX
error code: 123

Как мне это сделать?

решение1

Насколько я понимаю ваш вопрос, вы хотите этого

171023 03014426 1234 XXXX XXXXXXXX
error code: 123, pc=546, call=0,
171023 03110749 1234 XXXX XXXXXXXX
error code: 123, pc=546, call=0,

чтобы стало так:

171023 03014426 1234 XXXX XXXXXXXX
error code: 123
171023 03110749 1234 XXXX XXXXXXXX
error code: 123

Есть много способов сделать это, поэтому выбирайте тот, который вам нравится/предпочтительнее.

сед

$ sed 's/\(error code:[[:blank:]][[:digit:]]*\),.*/\1/' input.txt                                     
171023 03014426 1234 XXXX XXXXXXXX
error code: 123
171023 03110749 1234 XXXX XXXXXXXX
error code: 123

Если вы хотите внести изменения в исходный файл input.txt, используйте sed -iвместо простоsed

awk

$ awk -F ',' '/^error code/{$0=$1};1' input.txt                                                       
171023 03014426 1234 XXXX XXXXXXXX
error code: 123
171023 03110749 1234 XXXX XXXXXXXX
error code: 123

При таком подходе запятая рассматривается как разделитель столбцов (на языке awk — «полей»), поэтому здесь мы по сути находим строку, которая начинается с error codeтекста, и заменяем исходную строку только столбцом $1, который в вашем случае представляет собой все, что находится перед запятой, т. е. error code: 123.

awkнельзя редактировать текст (в большинстве версий), sed -iно вы всегда можете вывести данные в новый файл и заменить старый файл новым, например:

awk -F ',' '/^error code/{$0=$1};1' input.txt > new_data.txt && mv new_data.txt input.txt 

чистый баш

#!/usr/bin/env bash

# make temp file for writing stuff
temp=$(mktemp)

# read input file, make necessary changes, write to temp file
while IFS= read -r line;
do
    case $line in
        "error code:"*) printf "%s\n" "${line%%,*}" >> "$temp";;
        *) printf "%s\n" "$line" >> "$temp";;
    esac
done < "$1"
mv  "$temp" "$1"

Тестовый забег:

$ # before 
$ cat input.txt                                                                                       
171023 03014426 1234 XXXX XXXXXXXX
error code: 123, pc=546, call=0,
171023 03110749 1234 XXXX XXXXXXXX
error code: 123, pc=546, call=0,
$ # after
$ ./edit_error_codes.sh input.txt                                                                     
$ cat input.txt
171023 03014426 1234 XXXX XXXXXXXX
error code: 123
171023 03110749 1234 XXXX XXXXXXXX
error code: 123

решение2

Если строки, которые вы не хотите трогать, не содержат запятых, и вы всегда хотите удалить только первую запятую и все, что после нее, вы можете использовать очень простое выражение

$ sed 's/,.*//' file
171023 03014426 1234 XXXX XXXXXXXX
error code: 123
171023 03110749 1234 XXXX XXXXXXXX
error code: 123
  • s/old/new/заменитьoldnew
  • .*любое количество любых символов

Чтобы редактировать файл на месте, используйте sedопцию in-place, которая является -i. Если суффикс для файла резервной копии добавляется после -i, он автоматически записывает резервную копию исходного файла с этим расширением в тот же каталог, например

sed -i 's/,.*//' file

перезаписывает fileизмененным потоком, но

sed -i.orig 's/,.*//' file

записывает измененный поток fileи записывает новый файл file.origс исходным содержимым.

решение3

Вы можете использовать простую cutкоманду, чтобы сделать то, что вам нужно.

cut -d"," -f1 input.txt

Запишите его обратно в тот же файл.

cut -d"," -f1 input.txt | tee input.txt

Связанный контент