Bash 中的多个 sed 命令

Bash 中的多个 sed 命令

我有一个 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

答案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
    • IE:user.name1user.name2
  • "\($k):\(.[$k])"将形成一个字符串,代入$k.[$k]
  • 使用-r从输出字符串中删除引号(生的模式)

使用sed处理 JSON 会让您面临各种各样的问题...例如,您将如何处理以下(完全有效的 JSON)输入?

{
    "user.name1" :
        "hashed_password",
    "user.name2" :
        "hashed_password"
}

答案2

当您处理 JSON 等标准化输入时,通常最好使用适当的解析器而不是正则表达式。例如,您将正确转换任何转义序列(尽管对于您的特定输入数据,这可能无法实现!)。

不幸的是,coreutils 中没有很好的工具来处理 JSON。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()))'

答案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一组独立工作的命令,那么使用“-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使用这种方式是没有意义的,因为会为您完成这项工作。但是,例如,如果您想将换行符转换为带有尾随空格的分号,一种方法是:trtr

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

相关内容