использование sed: как защитить знаки препинания для замены

Ответ на вторую часть -преобразование файлов json в таблицу.

Использование:./json_to_table.sh *.json

#!/bin/bash

for i in "$@"; do
    file_content=$(sed -n 's/".*":"\(.*\)",\?/\1/p' "$i" | tr '\n' ' ')
    printf "%s %s\n" "$i" "$file_content"
done | column -t

Если вам не нужен красивый формат таблицы, вы можете удалить | column -tчасть (внизу, послеdone). Тогда поля строки будут разделены одним пробелом, следовательно, каждое будет иметь свою ширину. Он хорош для парсинга программами типа awk, sed, но неудобен для чтения человеком.

Примечание:после каждой записи в файле json, кроме последней, должна стоять запятая. Что я имею в виду:

"field8":"310000", <- here
"field9":"si", <-here
"field10":"2017-06-05" <- not here. Last record without comma.
}
0
01.08.2019, 18:33
2 ответа

Проблема со вторым примером в том, что он вообще не соответствует вашей строке. Он пытается сопоставить ^.\.xyz, то есть:<beginning of line><any character>.xyz. Но я подозреваю, что вы пытаетесь сопоставить <some characters>.xyz<end of line>. Пока для начала вам нужно удалить ^, а затем вам нужно выяснить, как именно определить <some characters>для вашей ситуации.

Но вам не нужны два вызова sed, потому что вы можете хранить шаблоны в sed. Если вы окружаете шаблон, который хотите сохранить с (экранированными скобками ), вы можете заменить их позже на\1(или \2для второго шаблона и так далее ).

Итак, вы хотите удалить file, а затем окончательное имя файла в этом:

*xyzfile 0 1 somefilebeingpointedto.xyz

Таким образом, шаблон, который, как я думаю, вы ищете, это (с буквальным текстом «файл» в нем):

<something to keep>file<something to keep><space><pattern without spaces until end of line>

Мы можем сопоставить это с:

^\(.*\)file\(.*\) [^ ]*$

Обратите внимание, что две части, которые мы хотим сохранить, заключены в (экранированные )круглые скобки. Если бы мы не хотели оставлять их на потом, мы могли бы опустить скобки(.*file.* [^ ]*)

Затем с подстановкой sed вы получите полную строку, которая выглядит как:

sed 's/^\(.*\)file\(.*\) [^ ]*$/\1\2/'
2
28.01.2020, 02:29

Точка в регулярном выражении sed означает Любой символ , но только один символ.
Таким образом, регулярное выражение ^.\.xyzозначает :С начала строки сопоставьте один символ, затем одну точку, а затем xyz. Вы можете иметь в виду :^.*\.xyz$, но это будет соответствовать всей строке (и стереть ее ). Вы должны использовать пробел в качестве разделителя (, предполагая, что имена файлов не содержат пробелов в имени ):[^ ]*\.xyz$, что означает, что :из пробела(" ")соответствует нескольким(*)не -пробелам([^ ])символам до расширения .xyzв конце строки ($). Вы можете выразить обе замены, если вы перед каждой частью ставите-e:

sed -e 's/^.*xyzfile/*xyz/' -e 's/ [^ ]*\.xyz$//' myfile.inp

Нет необходимости экранировать *в правой части замены.

Это можно упростить до:

sed -e 's/xyzfile /*xyz /' -e 's/ [^ ]*\.xyz$//' myfile.inp

Пробелы в имени файла

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

Если второе и третье поля имеют только один символ, вы можете использовать скобки захвата и поместить их обратно с помощью\1:

sed -e 's/xyzfile\(..\).*\.xyz$/xyz\1/' myfile.inp

В расширенный синтаксис регулярных выражений:

sed -E -e 's/xyzfile(..).*\.xyz$/xyz\1/' myfile.inp

Или,если бы поля могли иметь несколько символов (кроме пробела):

sed -E -e 's/xyzfile( [^ ]* [^ ]*).*\.xyz$/xyz\1/' myfile.inp

Это может привести к ошибке, если строка выглядит примерно так: (нетxyzfile):

*xyzffff 0 1 pointedto.xyz

В этом случае применяйте каждую замену независимо:

sed -E -e 's/xyzfile /xyz /' -e 's/( [^ ]* [^ ]*).*\.xyz$/\1/' myfile.inp
0
28.01.2020, 02:29

Теги

Похожие вопросы