Багато команд sed в Bash


3

У мене є файл імен користувачів і паролі в форматі JSON, які я хочу конвертувати в процес.

Я використав 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

Відповіді:


16

Щоб поставити кілька 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"
}

3

Коли ви маєте справу зі стандартизованим введенням, наприклад JSON, краще використовувати правильний парсер, а не регулярний вираз. Наприклад, ви правильно конвертуєте будь-які послідовності (хоча це може бути неможливо з вашими вхідними даними!).

На жаль, немає великих інструментів для роботи з JSON в межах coreutils. Надається Attie 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()))'

0

Для простого видалення символів ви робите в них 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 Команди, які кожен працює незалежно, комбінуючи їх, можна найлегше виконати за допомогою "-f" sed можливість прочитати окремі команди з файлу. Ви просто помістіть рядки 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 перетворює всі символи% в пари символів ";".)


0

Sed може обробляти багаторядковий редагування, але я погоджуюся з Attie і Bob, розбирати json з sed regex можуть стати кошмаром.

sed -nr '/\{/ b Load ; d
: Load
/\}/ b Edit ; N ; b Load
: Edit ; s/[^"]+"([^"]+)"[^"]+"([^"]+)"(.*)/\1:\2\n\3/ ; t Print ; d
: Print ; P ; s/[^\n]+\n// ; t Edit' <<'eof'
{
    "user.name1" :
        "hashed_password1",
    "user.name2" :
        "hashed_password2"
}
    { "user.name3" : "hashed_password3",
"user.name4" : "hashed_password4" }

{ "user.name5":"hashed_password5"}
eof

user.name1:hashed_password1
user.name2:hashed_password2
user.name3:hashed_password3
user.name4:hashed_password4
user.name5:hashed_password5

-1

Ви можете об'єднати це так:

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.