【问题标题】:unix - print distinct list of control characters in a fileunix - 在文件中打印不同的控制字符列表
【发布时间】:2012-01-30 23:45:08
【问题描述】:

例如给定如下输入文件:

sid|storeNo|latitude|longitude
2|1|-28.03õ720000
9|2
10
jgn
352|1|-28.03¿720000
9|2|fd¿kjhn422-405
000¥0543210|gf¿djk39
gfd|f¥d||fd

输出(下面的字符可以按任意顺序出现):

¿õ¥

有没有人有一个函数(awk、bash、perl.etc)可以扫描每一行,然后输出(八进制、十六进制或 ascii - 都可以)一个不同的控制字符列表(为简单起见,控制字符是那些高于 ascii char 126) 的吗?

使用 perl v5.8.8。

【问题讨论】:

  • 为什么不首先使用适当的字符集进行解码?
  • @Ignacio - 理想情况下,是的。但从外部来源接收数据,因此能够运行此检查将很有用。
  • Nit:只有一个“126 以上的 ascii char”,因为 ASCII 只有 128 个字符(编号 0-127)。当您说“ascii char”时,您的意思是“字节”。

标签: linux perl bash shell unix


【解决方案1】:

以八进制打印字节:

perl -ne'printf "%03o\n", ord for /[^\x09\x0A\x20-\x7E]/g' file  | sort -u

以十六进制打印字节:

perl -ne'printf "%02X\n", ord for /[^\x09\x0A\x20-\x7E]/g' file  | sort -u

打印原始字节:

perl -nE'say for /[^\x09\x0A\x20-\x7E]/g' file  | sort -u

【讨论】:

  • “%02X\n”是什么意思?
  • @toop, "%02X\n"printf 的格式模式。 ord 返回作为其参数传递的字符串的第一个字符的字符编号,默认值为$_
  • 谢谢,让它打印原始输入字符会有什么变化? IE。 ¿
【解决方案2】:

这应该可以捕获超过序数值 126 的所有内容,而无需明确清除异常值

#!/bin/bash

while IFS= read -n1 c; do 
  if (( $(printf "%d" "'$c") > 126)); then
    echo "$c"
  fi
done < ./infile | sort -u

输出

¥
¿
õ

【讨论】:

  • “IFS= read -n1 c;”是什么意思do 和 "'$c" 中的单引号是干什么用的?
【解决方案3】:

删除控制字符以外的所有内容:

tr -d '\0-\176' < input > output

测试:

printf 'foobar\n\377' | tr -d '\0-\176' | od -t c

详情请见tr(1) man page

【讨论】:

  • +1,我喜欢这个。 tr -d '\0-\177' &lt; ./infile| sed 's/./&amp;\n/g' | sort -u 得到 OP 正在寻找的东西。
【解决方案4】:
sed -e 's/[A-Za-z0-9,|]//g' -e 's/-//g' -e 's/./&^M/g' | sort -u

删除不需要的所有内容,将其他所有内容放在单独的行中,然后对整个套件进行排序。

“&^M”在 Bash 中是“&”后接 Ctrl-V 后接 Ctrl-M。

Unix 获胜。

【讨论】:

  • 输出“.”如果在输入中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-13
  • 2016-03-21
  • 1970-01-01
  • 2014-01-23
  • 2016-03-28
相关资源
最近更新 更多