我将输出分开,id
以提供一个更易读的逐行列表,其中包含用户所属的组:
id roaima | sed 's/,/\n\t/g'
uid=1001(roaima) gid=1001(roaima) groups=1001(roaima)
24(cdrom)
25(floppy)
...
822413650 (international (uk) location)
我想将组号与其括号中的名称分开,所以我像这样扩展了表达式
id roaima | sed -e 's/,/\n\t/g' -e '2,$s/(/ (/'
然而,这并没有像我最初预期的那样。第二个表达式似乎没有效果。
相反,为了获得我想要的结果,我需要运行两个单独的sed
命令,如下所示:
id roaima | sed -e 's/,/\n\t/g' | sed '2,$s/(/ (/'
uid=1001(roaima) gid=1001(roaima) groups=1001(roaima)
24 (cdrom)
25 (floppy)
...
822413650 (international (uk) location)
为什么在一个管道中需要两个sed
命令而不是一个包含多个指令的命令?或者如果我可以用一个来做到这一点sed
,我会怎么做?
我特别希望在每个项目的 UID/GID 值及其括号内的名称之间有一个空格(包括第一行的 UID 和 GID),但需要注意的是,在我的真实数据中,我可以有组他们的名字中包含括号,我不希望名字本身被破坏。
答案1
sed
,就像awk
or 或cut
一样,perl -ne
逐行分别作用于每一行。
sed -e code1 -e code2
实际上运行为:
while(patternspace = getline()) {
linenumber++
code1
code2
} continue {print patternspace}
如果你的 code2 是2,$ s/foo/bar/
,那就是:
if (linenumber >= 2) sub(/foo/, "bar", patternspace)
由于您的输入只有一行,因此sub()
永远不会运行。
在模式空间中插入换行符code1
不会导致linenumber
增加。
相反,在处理时,您有一个包含多行的模式空间第一的并且只有一行输入。如果您想对多行模式空间的第二行及以上进行修改,您需要执行以下操作:
s/\(\n[^(]*\)(/\1 (/g
当然,在这里,您也可以一次性完成这两个操作:
id | sed 's/,\([^(]*\)(/\n\t\1 (/g'
答案2
如果你有 GNU sed,你可以使用
id username | sed 's/(/ (/4g; s/,/\n\t/g'
它在第四个及其后的左括号之前添加一个空格,然后替换逗号。
答案3
@stéphane-chazelas 说的是真的,但你总是可以先添加空格,然后分成几行,如下所示:
sed -e 's:\([,=][0-9]*\):\1 :g' -e 's:,:\n\t:g'
或者在单个 sed 脚本中(不带-e
):
sed 's:\([,=][0-9]*\):\1 :g; s:,:\n\t:g'
我们通常使用“ /
”作为命令搜索的分隔符,但它也接受任何字符,因此有时使用“ :
”等其他字符更容易阅读,以避免像“ /\
”这样的组合。