У меня есть такой файл:
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/
заменитьold
new
.*
любое количество любых символов
Чтобы редактировать файл на месте, используйте 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