通过从另一个文件读取的 delim 拆分每一行,并将所有拆分词复合存储在结果文件中

通过从另一个文件读取的 delim 拆分每一行,并将所有拆分词复合存储在结果文件中

我想names按文件中的每个分隔符拆分文件中的每一行delim,并将唯一的单词复合存储到结果文件中compoundsnames应从输出文件中删除未拆分的行。只有 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 个元字符:

  1. " "这意味着 FS 中的“任何空格序列”,
  2. "+"这意味着正则表达式中“前面的表达式重复 1 次或多次”(如果它位于正则表达式的开头或跟随 a ,则未定义|),并且
  3. "-"如果它位于括号表达式内而不是第一个或最后一个字符,则表示“范围”。

因此,您不能像 delims 中的字符|那样创建一个分隔列表,|-|+|'因为这样 的含义+是未定义的,并且如果它单独存在的话,其含义<blank>也不是字面意思,也不能将它们全部包含在括号表达式[ -+']中的含义是从​​到 的-一系列字符,同样不是字面意思。<blank>+

我上面所做的是创建一个|- 分隔的括号表达式列表[ ]|[-]|[+]|['],因为这适用于 delims 可以包含的任何/所有字符。

答案3

使用grep,trsort:

注意:我们需要将-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

其中集合RSFS因此getline读取delims为一个单一的$0,然后重新组合它,$1=$1确保OFS=""我们不会添加任何意外的空格。

然后我们可以做一些小小的gsub调整,以$0确保-只发生在字符集的末尾(仅添加到if-的末尾是成功的 和),为您提供字符集为。FSgsubs>0[ '+-]FS

现在我们可以设置RS回,\n但我们也设置OFS\n

然后无论在哪里都一切照常NF>1,但是因为OFS="\n"我们不需要迭代,所以NF我们可以用$1=$1and重新组合print

相关内容