У меня есть файл с именами пользователей и паролями в формате JSON, который я хочу преобразовать в process.
Я использовал sed
разные команды для его обработки, но мне хотелось бы узнать, как объединить все три команды в одну на будущее.
Оригинальный формат
{ "user.name1" : "hashed_password",
"user.name2" : "hashed_password" }
Желаемый результат
user.name:hashed_password
Это команды, которые я выполнил, однако мне не удалось объединить их вместе ни с помощью конвейеризации, ни простого объединения, из-за чего я получаю ошибку sed: -e expression #1, char 8: unknown option to 's'
.
Оскорбительная команда...
sed -i 's/\"//g/s/\,/\n/g/\s//g' input_file
sed: -e expression #1, char 8: unknown option to `s'
Как можно объединить приведенные ниже команды в одну?
Команды Удалить двойные кавычки
sed -i 's/\"//g' input_file
Заменить запятую на новую строку
sed -i 's/\,/\n/g' input_file
Удалить пробелы
sed -i 's/\s//g input_file
решение1
Чтобы поместить несколько sed
команд в одну команду "сценарий", вы можете использовать несколько -e
флагов (что является переносимым):
sed -i -e 's/\"//g' -e 's/\,/\n/g' -e 's/\s//g' input_file
Или разделитель в виде точки с запятой (доступный не во всех реализациях):
sed -i 's/\"//g;s/\,/\n/g;s/\s//g' input_file
Вам также нужно будет добавить обработку скоб - {}
...
Сказав это, для правильного анализа и обработки JSON вам не следует использовать sed
... возможно, стоит попробоватьjq
!
jq -r 'keys[] as $k | "\($k):\(.[$k])"' input_file
Выход:
user.name1:hashed_password
user.name2:hashed_password
keys[] as $k
будет проходить по каждому ключу, сохраняя его значение в$k
- то есть:
user.name1
,user.name2
- то есть:
"\($k):\(.[$k])"
сформирует строку, подставляя в$k
и.[$k]
- Использование
-r
удаляет кавычки из выходных строк (сыройрежим)
Использование sed
JSON для обработки может привести к возникновению множества проблем... например, как бы вы поступили со следующими (полностью корректными) входными данными JSON?
{
"user.name1" :
"hashed_password",
"user.name2" :
"hashed_password"
}
решение2
Когда вы имеете дело со стандартизированным вводом, таким как JSON, обычно лучше использовать правильный парсер, а не регулярные выражения. Например, вы правильно преобразуете любые управляющие последовательности (хотя это может быть невозможно с вашими конкретными входными данными!).
К сожалению, в coreutils нет хороших инструментов для работы с JSON.Этти предоставил jq
как достойный вариант, если у вас есть возможность свободно устанавливать пакеты.
Если вы не можете установить дополнительные пакеты, это не так уж и сложно в Python. Возьмем, к примеру, этот скрипт:
import json,sys
for (k, v) in json.load(sys.stdin):
print(k + ":" + v)
Что можно сжать до одной строки:
cat inputdata | python -c 'import json,sys;print("\n".join((k + ":" + v) for (k, v) in json.load(sys.stdin).items()))'
решение3
Для простого удаления символов, которое вы делаете в этих sed
командах, я бы рекомендовал вам использовать tr
, единственной целью которого является удаление, сжатие или замена отдельных символов, включая символы новой строки ( sed
основан на регулярных выражениях, которые обычно полагаются на символы новой строки в качестве разделителей буфера, поэтому использование sed для изменения новых строк является сложным). Я думаю, что эта tr
команда делает все, что вы ищете:
cat json_filename | tr -d "{}\" \012\011\015" | tr "," "\012"
Первая tr
команда удаляет все фигурные скобки, двойные кавычки, пробелы, символы возврата каретки (восьмеричный 012, ASCII 10), табуляции (восьмеричный 011, ASCII 9 и перевода строки (восьмеричный 015, ASCII 13). Вторая tr
команда заменяет все запятые на символы возврата каретки. Если имена и значения переменных вашего файла JSON не содержат запятых, эти команды позволят вам избежать необходимости в специальном парсере JSON.
Тем не менее, если у вас есть набор sed
команд, каждая из которых работает независимо, их объединение может быть наиболее простым способом, используя sed
опцию "-f" для чтения отдельных команд из файла. Вы просто помещаете строки s/.../.../g в файл, каждую строку на отдельной строке, затем указываете это имя файла после опции "-f". Например, если три sed
перечисленные вами команды вас устраивают, вы можете поместить их в файл с именем "json.convert.sed", который просто содержит это:
s/\"//g
s/\,/\n/g
s/\s//g
Затем вы можете вызвать sed
этот командный файл, используя:
sed -f json.convert.sed
Тем не менее, эти sed
команды не работают для меня, чтобы добиться того, что вы хотите, и я не уверен, что вы когда-либо сможете sed
изменить символы новой строки. Это потому, sed
что основан на старом редакторе строк "ed", разработанном для редактирования отдельных строк за раз (его "скриптовая" версия), поэтому каждая строка ввода "анализируется" с использованием новых строк в качестве разделителей, затем строка (без новой строки) передается в механизм редактирования, применяются команды редактирования, затем отредактированная строка выводится с новой строкой. Затем цикл повторяется. Я когда-либо мог использовать sed
для изменения новой строки только сначала изменив новые строки на какой-либо отдельный символ (который иначе не появляется во входных данных) с помощью tr
. Нет смысла использовать tr
этот способ, если все, что вам нужно сделать, это удалить новые строки, так как tr
сделает это за вас. Но если, например, вы хотите преобразовать новые строки в точки с запятой с конечным пробелом, один из способов сделать это будет:
cat input_file | tr "\012" "%" | sed "s/%/; /g"
(символы новой строки преобразуются в % с помощью tr
, а затем sed
преобразуются все символы % в пары символов "; ".)
решение4
Вы можете объединить это следующим образом:
sed -i 's/\"//g;s/\,/\n/g;s/\s//g' input_file
Вы забыли добавить удаление {}
. Так что вы, вероятно, хотите:
sed -i 's/\"//g;s/\,/\n/g;s/\s//g;s/{//g;s/}//g' input_file