我想names
按文件中的每个分隔符拆分文件中的每一行delim
,并将唯一的单词复合存储到结果文件中compounds
。names
应从输出文件中删除未拆分的行。只有 4 个分隔符:-'+
重要的:names
文件包含 utf-8 编码的人名。
$ cat delims
(space is here)
-
'
+
$ cat names
Tania
Günter
Abdel+Aziz
Abdel'Piza
Märie-Pierre
输出化合物文件应该是(顺序无关紧要):
Abdel
Aziz
Piza
Märie
Pierre
答案1
如果您有一个允许字段分隔符扩展正则表达式的 awk,那么您可以执行类似的操作
$ awk '
BEGIN{FS=""; while((getline < "delim") > 0){FS = FS=="" ? $0 : FS"|"$0}}
NF>1 {for(i=1;i<=NF;i++) print $i}
' names
Abdel
Aziz
Abdel
Piza
Märie
Pierre
注意:使用字符集[ '+-]
而不是正则表达式替换可以说会更干净|'|+|-
(并且还可以消除对于+
文字量词还是正则表达式量词可能产生的混淆)。然而,这需要仔细地对条目进行洗牌,因为-
内部[...]
是范围运算符,除非在开始或结束处。
答案2
对于示例中的 4 个字符,这将可靠且可移植地工作:
$ cat tst.awk
NR==FNR {
FS = (NR > 1 ? FS "|" : "") "[" $0 "]"
next
}
NF > 1 {
for ( i=1; i<=NF; i++ ) {
if ( !seen[$i]++ ) {
print $i
}
}
}
。
$ awk -f tst.awk delims names
Abdel
Aziz
Piza
Märie
Pierre
这里所需的复杂性是因为 4 个分隔符集中有 3 个元字符:
" "
这意味着 FS 中的“任何空格序列”,"+"
这意味着正则表达式中“前面的表达式重复 1 次或多次”(如果它位于正则表达式的开头或跟随 a ,则未定义|
),并且"-"
如果它位于括号表达式内而不是第一个或最后一个字符,则表示“范围”。
因此,您不能像 delims 中的字符|
那样创建一个分隔列表,|-|+|'
因为这样 的含义+
是未定义的,并且如果它单独存在的话,其含义<blank>
也不是字面意思,也不能将它们全部包含在括号表达式[ -+']
中的含义是从到 的-
一系列字符,同样不是字面意思。<blank>
+
我上面所做的是创建一个|
- 分隔的括号表达式列表[ ]|[-]|[+]|[']
,因为这适用于 delims 可以包含的任何/所有字符。
答案3
使用grep
,tr
和sort
:
注意:我们需要将-
in移动delims
到文件的顶部或底部(否则tr
会认为存在一个范围)。
获取所有包含分隔符的行grep
并用换行符替换所有分隔符(使用 获取所有delims
不带换行符的字符tr -d '\n' < delims
)。
将结果通过管道传送到 来sort -u
消除重复并将输出重定向到compounds
.
grep -F -f delims names | tr -- "$(tr -d '\n' < delims)" '\n' | sort -u > compounds
输出:
$ cat compounds
Abdel
Aziz
Märie
Pierre
Piza
答案4
你也可以....
awk 'BEGIN{OFS=RS="";FS="\n"; getline;$1=$1;
s=gsub("-","",$0);FS="["$0((s>0)?"-":"")"]";
OFS=RS="\n"}
NF>1{$1=$1; print}' delims names
Abdel
Aziz
Abdel
Piza
Märie
Pierre
其中集合RS
和FS
因此getline
读取delims
为一个单一的$0
,然后重新组合它,$1=$1
确保OFS=""
我们不会添加任何意外的空格。
然后我们可以做一些小小的gsub
调整,以$0
确保-
只发生在字符集的末尾(仅添加到if-
的末尾是成功的 和),为您提供字符集为。FS
gsub
s>0
[ '+-]
FS
现在我们可以设置RS
回,\n
但我们也设置OFS
为\n
。
然后无论在哪里都一切照常NF>1
,但是因为OFS="\n"
我们不需要迭代,所以NF
我们可以用$1=$1
and重新组合print