我想使用 cut to 和 2 个字符分隔符来处理包含许多行的文件,如下所示:
1F3C6..1F3CA
1F3CF..1F3D3
1F3E0..1F3F0
但 cut 只允许单个字符。
而不是cut -d'..'
我正在尝试,awk -F'..' "{echo $1}"
但它不起作用。
我的脚本:
wget -O output.txt http://www.unicode.org/Public/emoji/6.0/emoji-data.txt
sed -i '/^#/ d' output.txt # Remove comments
cat output.txt | cut -d' ' -f1 | while read line ;
do echo $line | awk -F'..' "{echo $1}"
done
答案1
awk
只要 的字段分隔符超过两个字符,就会被视为正则表达式。..
作为正则表达式,表示任意 2 个字符。你需要.
用[.]
或 with 来逃避它\.
。
awk -F'[.][.]' ...
awk -F'\\.\\.' ...
(反斜杠本身也需要转义(至少对于一些像 gawk 这样的 awk 来说),以便参数进行\n
/扩展)。\b
-F
在你的情况下:
awk -F' +|[.][.]' '/^[^#]/{print $1}' < output.txt
任何状况之下,避免 shell 循环处理文本, 注意read
不应该这样使用, 那echo
不应该用于任意数据和记得引用你的变量。
答案2
对我有用的示例测试脚本:
#!/bin/sh
raw="1F3C6..1F3CA
1F3CF..1F3D3
1F3E0..1F3F0"
for r in $raw
do
f1=`echo "${r}" | cut -d'.' -f1`
f2=`echo "${r}" | cut -d'.' -f2`
f3=`echo "${r}" | cut -d'.' -f3`
echo "field 1:[${f1}] field 2:[${f2}] field 3:[${f3}]"
done
exit
输出是:
field 1:[1F3C6] field 2:[] field 3:[1F3CA]
field 1:[1F3CF] field 2:[] field 3:[1F3D3]
field 1:[1F3E0] field 2:[] field 3:[1F3F0]
编辑
阅读 Stéphane Chazelas 评论和链接的问答后,我重写了上面的内容以删除loop
.
我无法找到一种方法来删除loop
和将这些部分保留为可以传递的变量(例如;$f1
,$f2
以及在我原来的答案中)。$f3
我仍然不知道原始问题中需要输出什么。
首先,仍然使用cut
:
#!/bin/sh
raw="1F3C6..1F3CA
1F3CF..1F3D3
1F3E0..1F3F0"
printf '%s\n' "${raw}" | cut -d'.' -f1,3
这将输出:
1F3C6.1F3CA
1F3CF.1F3D3
1F3E0.1F3F0
.
可以使用--output-delimiter=STRING
.替换显示的任何字符串。
接下来,用 withsed
代替,cut
以便更好地控制输出:
#!/bin/sh
raw="1F3C6..1F3CA
1F3CF..1F3D3
1F3E0..1F3F0"
printf '%s\n' "${raw}" | sed 's/^\(.*\)\.\.\(.*\)$/field 1 [\1] field 2 [\2]/'
这将呈现:
field 1 [1F3C6] field 2 [1F3CA]
field 1 [1F3CF] field 2 [1F3D3]
field 1 [1F3E0] field 2 [1F3F0]
答案3
您可以使用 IFS 分割每一行,丢弃两个点之间的字段:
#/bin/sh
while IFS=\. read a _ b
do
echo "field one=[$a] field two=[$b]"
done < "file"
执行:
$ ./script
field one=1F3C6 field two=1F3CA
field one=1F3CF field two=1F3D3
field one=1F3E0 field two=1F3F0
假设该文件是:
$ cat file
1F3C6..1F3CA
1F3CF..1F3D3
1F3E0..1F3F0