我有这个查询
sed '/./=' abc.txt| sed '/./N; s/\n/, /' >> as.dat
source file has 3 rows like below
a
b
c
当使用以下命令时,它会给我这样的结果
Output
1 a
2 b
3 c
但我想要这样的命令输出
Output
a 1
b 2
c 3
答案1
Unix 有这些奇妙的小工具,称为cut
和paste
。该cut
工具将从其输入中提取一组列,同时paste
插入列。我们将使用这些。
我不会太关心你的管道(现在,但请参阅这个答案的结尾),我只关心切换列的问题。
假设我有一个名为的文件中的数据cols.txt
:
$ cat cols.txt
1 a
2 b
3 c
$ paste -d ' ' cols.txt cols.txt
1 a 1 a
2 b 2 b
3 c 3 c
该paste
实用程序通常会在列之间插入一个制表符,但在这里我们告诉它插入一个空格 ( -d ' '
)。
paste
然后只需从with 的输出中提取第二列和第三列即可cut
:
$ paste -d ' ' cols.txt cols.txt | cut -d ' ' -f 2,3
a 1
b 2
c 3
我们已经说过cut
,我们有空格作为“字段分隔符”(-d ' '
,否则需要制表符),并且我们希望有字段 2 和 3 ( -f 2,3
)。 (不幸的是,只要求原始输入中的cut
列“ ”2,1
不是交换列。)
所以最终这里真的不需要混乱的正则表达式魔法。
回到你的管道。让我们废弃它吧。似乎您想将行号插入到每一行中。还有另一个 Unix 工具叫做nl
(“数字线”):
$ nl abc.txt
1 a
2 b
3 c
默认情况下,您会获得每个非空行的行号,前面有一些用于填充的空格,并通过制表符与原始行分隔。您是否也想对空行进行编号,请使用
$ nl -b a abc.txt
据我所知,您无法nl
将行号放在行的右侧,但这不是问题,因为我们有一个解决方案可以交换两列输入:
$ paste <(nl abc.txt) <(nl abc.txt) | cut -f 2,3
a 1
b 2
c 3
我们不再需要在这里指定分隔符。nl
将在每行的开头插入空格,后跟行号和制表符。paste
在列之间插入制表符,并cut
在制表符上剪切,这样它就可以工作了。
如果您希望列之间有一个空格(现在有一个制表符和一些空格),请添加| tr -s '\t' ' '
到命令中。这会将所有制表符更改(“音译”)为空格,并将-s
所得的连续空格“压缩”( ) 为一个空格。
如果您想要一个逗号和一个空格,请改用| tr '\t ' ', '
:
$ paste <(nl abc.txt) <(nl abc.txt) | cut -f 2,3 | tr -s '\t ' ', '
a, 1
b, 2
c, 3
这适用于每行包含多个单词的文件,但对于包含制表符的文件将失败:
$ cat abc.txt # no tabs in this file though
a text there is a
b goes hole in my
c here pants
$ paste <(nl abc.txt) <(nl abc.txt) | cut -f 2,3
a text there is a 1
b goes hole in my 2
c here pants 3
答案2
sed '/./=' | sed '/./{N; s/\(.*\)\n\(.*\)/\2 \1/;}'
但awk
会更直接:
awk '/./ {$0 = $0 " " NR}; {print}'
您只会对包含至少一个字符的行进行编号,这似乎很奇怪。如果这不是您的意图,那么您可以将其更改为:
sed = | sed 'N; s/\(.*\)\n\(.*\)/\2 \1/'
awk '{print $0, NR}'
答案3
完成任务的另一种方法是使用nl
带选项的命令-nln
。这对文件中的行进行编号。例如..
echo -e "a\nb\nc\n" | nl -nln -
会产生:
1 a
2 b
3 c
现在剩下的就是将数字移到单词的右侧。这可以使用sed
以下方法完成:
sed 's/^\([^ \t]*\)[ \t]*\([^ \t].*\)$/\2 \1/g'
它的作用是找到一行中的第一个单词(要找到第一个单词,我们必须只包含除空格和制表符之外的那些字符。这是使用 完成的[^ \t]
)并将其记住为\1
以及 空格后面的行部分 为\2
并替换与 的行\2 \1
。
所以最终的命令是
cat filename | nl -nln - | sed 's/^\([^ \t]*\)[ \t]*\([^ \t].*\)$/\2 \1/g'