有一个文件,a.txt ,文容如下:
0689LM name=S:321, password=154adfv839473, value=37461278216723
1633LM name=S:241, password=15sdf78839611, value=21
1121LM name=S:673, password=1543978839612, value=1230
1212LM name=S:854, password=fd43978df9621, value=383242544
3323LM name=S:456, password=sd9788396sdd3, value=11211
3322LM name=S:234, password=dsfas78839623, value=23121
4238LM name=S:254, password=1fdsafdsafdsa, value=324342
51LM name=S:903, password=fdsafsdafsdaf, value=43543
2389LM name=S:572, password=fdsfdsdfwefff, value=2343235
91452LM name=S:842, password=sdfwef23dffds, value=3434324
9553LM name=S:fed, password=23fdssfdss32f, value=10501342176
需求:输出第一列的反转,name=S:之后的数字,value 之后的数值,如下:
ML9860 321 37461278216723
ML3361 241 21
ML1211 673 1230
ML2121 854 383242544
ML3233 456 11211
ML2233 234 23121
ML8324 254 324342
ML15 903 43543
ML9832 572 2343235
ML25419 842 3434324
ML3559 fed 10501342176
awk,不好实现第一列的反转
sed,不好显示抓取 name=S:之后的数字(需要非贪婪)
当然,也可能是我才疏学浅,如果各位大佬有更好的解决方法,欢迎指教。
perl -aE '/name=S:(.*?),.*?value=(.*)/; $a = reverse $F[0]; say "$a $1 $2"' a.txt
1
liprais 2018-12-05 20:46:02 +08:00
想用 perl 就用 perl 呗
反正之后你会发现三十秒看不懂的东西都得重写 |
3
zbinlin 2018-12-05 20:59:28 +08:00
只用 sed 就可以呀:
sed -r 's/^([[:digit:]]+)([A-Z]+)\s+name=S:([^,]+),.+value=(.+)$/\2\1 \3 \4/' |
6
yiyiwa 2018-12-05 21:14:05 +08:00
这样有点慢啊
awk -F '[: ,]' '{"rev<<<"$1|getline a;print a,$3,$NF}' |
7
yiyiwa 2018-12-05 21:19:10 +08:00
少个+,
awk -F '[: ,]+' '{"rev<<<"$1|getline a;print a,$3,$NF}' |
8
hujianxin OP @yiyiwa 这条语句在我这里有语法错误呢
sh: 1: Syntax error: redirection unexpected name=S value=37461278216723 sh: 1: Syntax error: redirection unexpected name=S value=21 sh: 1: Syntax error: redirection unexpected name=S value=1230 sh: 1: Syntax error: redirection unexpected name=S value=383242544 sh: 1: Syntax error: redirection unexpected name=S value=11211 sh: 1: Syntax error: redirection unexpected name=S value=23121 sh: 1: Syntax error: redirection unexpected name=S value=324342 sh: 1: Syntax error: redirection unexpected value=43543 sh: 1: Syntax error: redirection unexpected name=S value=2343235 sh: 1: Syntax error: redirection unexpected 842 value=3434324 sh: 1: Syntax error: redirection unexpected |
10
yiyiwa 2018-12-05 21:25:53 +08:00
awk -F '[: ,=]+' '{s=length($1);for(i=0;i<s;i++)k=k""substr($1,s-i,1);print k,$4,$NF;k=j}'
|
11
rrfeng 2018-12-05 21:27:50 +08:00
翻转第一列:
echo .... | while read a b; do echo $(rev <<< $a) $b;done 如果只有一行的话不需要 while echo .... | { read a b; echo $(rev <<< $a) $b; } |
12
weyou 2018-12-05 21:29:06 +08:00 via Android
首先 awk 是可以用循环来反转的,就是麻烦点。第二,rev 命令很多系统都是自带的吧,为什么不用
|
14
ywgx 2018-12-05 21:34:02 +08:00 1
对 vimer 来说,也就是录制个宏,播放一下而已
|
15
hcymk2 2018-12-05 21:38:08 +08:00
awk 可以自定义函数。
|
16
hujianxin OP |
17
codechaser 2018-12-05 22:18:46 +08:00 via Android
你们说的我根本看不懂……
|
18
likuku 2018-12-05 22:26:58 +08:00
额... 我是突然点进了今天的 黑魔法 9 级课程了么?
别说 awk sed 了,shell 开始需要用到 判断 语句 我都果断直接用 py3 了。 |
19
zbinlin 2018-12-05 22:35:34 +08:00 1
@zbinlin
paste -d' ' <(sed -rn 's/^([^ ]+*).+$/\1/p' <filename> | rev) <(sed -rn 's/^.+name=S:([^,]+),.+value=(.+)$/\1 \2/p' <filename>) |
20
ToT 2018-12-05 23:24:40 +08:00
能用 pandas 么。。。。
|
21
xpresslink 2018-12-05 23:37:00 +08:00
随便用个编程语言打开文件逐行遍历一下就可以。
|
22
DAPTX4869 2018-12-05 23:59:05 +08:00
shell 这堆玩意....瞎了
|
23
realpg 2018-12-06 00:33:23 +08:00
python 不好么
其实更好的解决方案是 EXCEL |
24
livepps 2018-12-06 00:47:41 +08:00 via Android
python 分分钟的事情
|
25
agagega 2018-12-06 01:03:06 +08:00
我想了想用 Ruby,也可以一行搞定,结果可能可读性比你的 Perl 稍微高点点,也没差太多...
|
26
yue9944882 2018-12-06 01:05:37 +08:00 2
写 perl 很多年了。。perl 现在实战的价值就是所谓 one-liner。。谁写的更精简谁就更好,不管可读性。。这也是 perl 同 python 等其他“更高级”的语言的一个优势吧。。有点像所谓降维打击哈哈哈
(不要学 perl 了,浪费时间) |
27
congeec 2018-12-06 01:15:00 +08:00 1
#23 说的对
我都复制下来,放 excel 里 写正则还要查一会儿语法 |
29
thedrwu 2018-12-06 03:00:14 +08:00 via Android
perl 作为主力脚本语言十多年,自从因为 numpy 用了 Python,发现回不去 perl 了:
连 foreach 都不会写了, 哪些操作会影响$_也忘了。 嗯?这里的引用要套几层? 从前的我怎么到处都在用 qw,那是干啥的现在怎么想不起来了… 重新学 perl 好麻烦,还是退回 bash+sed+awk 算了。 |
30
congeec 2018-12-06 03:04:48 +08:00
@Tony042 假设你用 mac, 用 pbcopy/pbpaste 来复制粘贴。windows 也有类似的工具,不过你要自己找
tips:column 是个很好用的表格格式化命令 |
32
Mithrandir 2018-12-06 09:07:54 +08:00
为啥不用 python,或者 awk + sed + python -c
|
33
swordne 2018-12-06 09:40:11 +08:00
为啥我觉得这东西在 excel 里就能完成了?
|
34
bellucci1964 2018-12-06 09:56:48 +08:00
说 python 就算了,说 excel 的又是什么鬼,ssh 到远程主机上哪来的 excel
|
35
julypanda 2018-12-06 10:01:26 +08:00
不会发图,手动表情
“这就是强者的世界吗?” |
36
hujianxin OP 不会发图,手动表情
“ talk is cheap, show me your code or excel picture ” |
37
thecon 2018-12-06 10:38:52 +08:00
正解,oneliner 目前还没有什么能比 perl 更趁手的吧
|
38
bucuoo 2018-12-06 10:40:33 +08:00
awk 版本
awk '{gsub(/[[:digit:]]+/,"&=",$1); split($1,aa,"="); split($2,na,"[=:,]"); split($4,va,"="); print aa[2]aa[1]" "na[3]" "va[2]}' a.txt |
40
hujianxin OP @thecon
简单的任务,awk 更简洁,输入的字符更少,比如我需要看 nginx 日志里面的服务器错误的 log,只需要:awk '$4>=500'。 但是复杂点的任务,比如我题目中提到的,perl 又更简洁很多,毕竟提供了功能强大的函数。 如果再复杂的任务,谁还用 oneliner 啊,哈哈 |
42
qinrui 2018-12-06 10:53:33 +08:00
反转是什么鬼?为什么要反转
|
43
zjsxwc 2018-12-06 11:32:50 +08:00
|
44
operawang 2018-12-06 11:36:28 +08:00
文本处理当然是 Perl 当家
|
45
jjianwen68 2018-12-06 11:40:43 +08:00
写不来这么复杂的 shell
|
46
xiaket 2018-12-06 11:46:11 +08:00
```{~}cat a.txt | python3 -c "import sys; \
> seg1 = lambda line: ''.join(reversed(line.split()[0])); \ > seg2 = lambda line: line.split()[1].split(':')[1].rstrip(','); \ > seg3 = lambda line: line.split()[-1].split('=')[-1]; \ > print(''.join(' '.join([seg1(line), seg2(line), seg3(line), '\n']) for line in sys.stdin.readlines()))"``` 好吧, 这么纠结的需求要放进一行,Python 的效果也一般. |
47
msg7086 2018-12-06 13:19:08 +08:00
喜欢 Perl 处理文本的可以试试 Ruby ……
|
48
buhi 2018-12-06 13:49:24 +08:00
真的是把 shell 这坨狗屎当成宝了...
|
49
ecmascript2020 2018-12-06 14:38:18 +08:00
用 javascript
|
51
xingheng 2018-12-06 15:56:07 +08:00
用 awk 和 shell 可以实现:
先分片,找到所有期望的元素: awk -F '[[:space:]]+|:|,|=' '{ print $1" "$4" "$10 }' 然后用 rev 实现反转: awk '{ system("echo $(echo "$1" | rev) " ); }' 拼起来: awk -F '[[:space:]]+|:|,|=' '{ system("echo $(echo "$1" | rev) " $4" "$10); }' 看了一下我的环境,rev 是 BSD 的命令,Linux 和 macOS 都内置 |
52
no1xsyzy 2018-12-06 15:57:59 +08:00
|
54
buhi 2018-12-06 16:01:39 +08:00
shell 从各方面来说作为一个编程语言都是不合格的, 任何正常的编程语言, 包括被人当成梗鄙视的 php, 都能吊打 shell 七条街, 这个就是屎的定义
|
56
Vegetable 2018-12-06 16:02:32 +08:00
工具是在进步的吧,没必要虐待自己不是?
|
58
hujianxin OP @buhi 并没有题目中有提 shell 语言吗?提的时 awk、sed、perl。你是不是想喷人想疯了?搞一个假想敌就开始喷
|
59
araraloren 2018-12-06 16:10:48 +08:00
cat **FILE** | perl6 -ne '/ ^ (.*?) \s+ .* \:(\w+) .* "value=" (\d+) $/; say ($0.comb.reverse.join, $1, $2).join("\t")'
你可以一行行的处理,perl 同理。。 |
60
MarioLuisGarcia 2018-12-06 16:14:35 +08:00
vim macro
|
61
hawhaw 2018-12-06 16:38:06 +08:00
perl 还是太老了
但这货实在是强大 几乎啥场景都能找到包 直接用 |
62
urmyfaith 2018-12-06 16:47:29 +08:00
![]( )
你们要到 Excel |
63
ltux 2018-12-06 16:49:57 +08:00
这种问题本来就是 Perl 的强项,awk sed 之类的工具本来压根本就不用学,一门 Perl 走天下即可。 上面说写了后来看不懂的,你写 sed awk 过几天照样看不懂。
|
65
loopfor 2018-12-06 16:53:58 +08:00
我觉得这种还是 java/c#/c++顺手。
那些一两行的看似精简,但是可维护性可读性都很差呀,出点问题调试也很麻烦。 |
66
araraloren 2018-12-06 17:04:56 +08:00
@loopfor 但是不是所有东西都需要维护的。。这东西就是用完就扔,下次再写
|
67
yiyizym 2018-12-06 17:20:00 +08:00
用 awk,自定义一个反转函数:rev
awk 'function rev(str){if(str == "") return ""; else return (rev(substr(str,2)) substr(str,1,1))} {print rev($1), substr($2,8), substr($4,7)}' a.txt |
69
yiyizym 2018-12-06 17:32:12 +08:00
@yiyizym
第二列多了个逗号,而且把 fed 也算进去了,更正一下: awk 'function rev(str){if(str == "") return ""; else return (rev(substr(str,2)) substr(str,1,1))} {print rev($1), gensub(/[^0-9]/,"","g",$2), substr($4,7)}' a.txt |
70
hellolleh 2018-12-06 18:00:10 +08:00
why not python?
|
71
lululau 2018-12-06 18:17:22 +08:00 2
说 Python 的可以试试能不能一分钟之内写出代码来,是的,像这样的不太复杂的文本处理任务用 Perl 一分钟之内就可以写出来代码
说 Excel 的可以试试算个一千万行或者更大的文本试试? Perl 相比 sed / awk 的优势是,你不许区分 perl 还是 gperl,不许记哪些选项和功能是只有 GNU 版本的才有,不需要去区分 basic regex, extended regex, posix regex,你只要会 Perl 正则就可以了 sed 算是门艺术,偶尔写一下可以陶冶情操,贴一个 sed 实现 rev 的代码,陶冶一下😀 sed '/\n/!G;s/\(.\)\(.*\n\)/&\2\1/;//D;s/.//' |
73
Raymon111111 2018-12-06 18:52:02 +08:00
哎呀 java 也可以其实(手动斜眼
|
74
no1xsyzy 2018-12-06 19:24:40 +08:00 1
@hujianxin “脑子混乱”并不是指我,而是写出 shell 的人。
一会想要以简短的字符表明一个意思,比如$+一个字符的那些(这不查那大部头 manual 根本不知道意思); 一会又不允许简洁地表达,比如单引号的处理(如何在单引号的引用字符串内放一个单引号?先结束前一段单引号字符串,反斜杠转义一个单引号进去,再开启下一段单引号字符,1->4 比反引号地狱还快)。 这纯是由于 shell 根本不是固定的一个人写的,甚至不是为了同一个目的设计的特性。 毫无主见地随波逐流地写特性出来。 只因为“之前有这个特性所以我们还是要保留这个特性”。 向后兼容只会造成过去的麻烦依旧堆积在那边。 |
76
no1xsyzy 2018-12-06 19:32:35 +08:00
@lululau ……能,连 re 都不用
x=input()之后用 split 爆,一行内分别是 ''.join(reversed(x.split(" ")[0])) x.split("name=S:")[1].split(",")[0] x.split(", value=")[-1] 用 print 输出 然后因为任意多行的要求,整个框在 while True 里面 总共写了 40 多秒 |
80
Kirscheis 2018-12-06 20:27:02 +08:00 1
import re
n = re.compile(r'''name=S:(.{3})''') m = re.compile(r'''value=(\d*)''') with open('asdf','r') as f: s = f.readlines() for i in s: a,b,c,d = i.split() a = a[::-1] b = n.match(b).groups()[0] d = m.match(d).groups()[0] print(a, b ,d) python,写了 30 秒左右吧。 不是说 perl 这些不好,我个人认为新的这些脚本语言的一个优点是,即使没有接触过编程的人,也能大概猜出来它想干什么,因此在过些年过气之后,不至于让大家都觉得遗留的脚本是天书。 |
82
lululau 2018-12-06 21:27:02 +08:00 via iPhone
学开汽车比学开飞机容易,所以汽车比飞机好,见识短没关系,但是保持开放的心态,先了解再判断
|
84
ps1aniuge 2018-12-07 13:53:42 +08:00
#建议保存编码为:bom 头 + utf8
$输入文件 = 'a:\pscode\TEMP_2018\temp207\aaa.txt' $输出文件 = 'a:\pscode\TEMP_2018\temp207\aaa2.txt' function 翻转函数($a) { $b = $a.tochararray() [System.Array]::Reverse($b) [string]$c = [system.String]::Concat($b) return $c } $所有行 = Get-Content -LiteralPath $输入文件 -ReadCount 0 $输出的所有行 = @() foreach ($行 in $所有行) { $列 = $行.split(' ',[System.StringSplitOptions]::RemoveEmptyEntries) $列 1 = 翻转函数 $列[0] $列 2 = $列[1].replace('name=S:','').trimend(',') $列 3 = $列[3].replace('value=','') $新列 = $列 1,$列 2,$列 3 -join ' ' $输出的所有行 += $新列 } Set-Content -LiteralPath $输出文件 -Encoding UTF8 -Value $输出的所有行 powrshell 代码,win,linux 通用。 源文件不要有尾部空行。 测试通过。 |
85
ps1aniuge 2018-12-07 13:56:48 +08:00
$列 3 被 V2EX 人为分词了,不怪我
|
86
ps1aniuge 2018-12-07 14:44:43 +08:00
用法:
在 linux 的 bash 中,用我分享的 powershell 脚本的方法:(需要先安装 linux 版 powershell ) /usr/bin/pwsh -f "fz 翻转字符串.ps1" -输入字符串 'abcd' #建议保存编码为:bom 头 + utf8 param ( [string]$输入字符串 ) $b = $输入字符串.tochararray() [System.Array]::Reverse($b) $c = [system.String]::Concat($b) return $c |