У меня есть файл вроде:
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
Как я могу это сделать?
Как я понимаю ваш вопрос, вы хотите, чтобы этот
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
Существует много способов сделать это, поэтому выберите способ, который вы хотите /like/prefer.
$ 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 -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-talk «поле») разделитель, поэтому здесь мы в основном находим строку, которая начинается с текста 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
Если строки, которые вы не хотите касаться, не имеют запятых, и вы всегда хотите только удалить первую запятую и все после нее, вы можете использовать очень простое выражение
$ 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 на месте, которая является -i. Если после -i добавлен суффикс для файла резервной копии, он автоматически записывает резервную копию исходного файла с этим расширением в том же каталоге, например
sed -i 's/,.*//' file
перезаписывает file с измененным stream, но
sed -i.orig 's/,.*//' file
записывает измененный поток в file и записывает новый файл file.orig с исходным содержимым.
Вы можете использовать простую команду cut, чтобы делать то, что вы хотите.
cut -d"," -f1 input.txt
Записать ее в тот же файл.
cut -d"," -f1 input.txt | tee 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,
стал следующим:
171023 03014426 1234 XXXX XXXXXXXX
error code: 123
171023 03110749 1234 XXXX XXXXXXXX
error code: 123
Существует много способов сделать это, поэтому выберите способ, который вы хотите /like/prefer.
$ 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 -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-talk «поле») разделитель, поэтому здесь мы в основном находим строку, которая начинается с текста 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
Если строки, которые вы не хотите касаться, не имеют запятых, и вы всегда хотите только удалить первую запятую и все после нее, вы можете использовать очень простое выражение
$ 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 на месте, которая является -i. Если после -i добавлен суффикс для файла резервной копии, он автоматически записывает резервную копию исходного файла с этим расширением в том же каталоге, например
sed -i 's/,.*//' file
перезаписывает file с измененным stream, но
sed -i.orig 's/,.*//' file
записывает измененный поток в file и записывает новый файл file.orig с исходным содержимым.
Вы можете использовать простую команду cut, чтобы делать то, что вы хотите.
cut -d"," -f1 input.txt
Записать ее в тот же файл.
cut -d"," -f1 input.txt | tee input.txt