多域Awk滤波

多域Awk滤波,awk,Awk,假设我有以下文本文件(它可以有更多的州、城市和学院): begin_state New York end_state begin_cities Albany Buffalo Syracuse end_cities begin_colleges Cornell Columbia Stony Brook end_colleges begin_state California end_ state begin_cities San Francisco Sacramento Los Angele

假设我有以下文本文件(它可以有更多的州、城市和学院):

begin_state
New York
end_state

begin_cities
Albany
Buffalo
Syracuse
end_cities

begin_colleges
Cornell
Columbia
Stony Brook
end_colleges

begin_state
California
end_ state

begin_cities
San Francisco
Sacramento
Los Angeles
end cities

begin_colleges
Berkeley
Stanford
Caltech
end_colleges
我想使用awk过滤所有城市并将它们列在州下,或者选择所有学院并将它们列在州下:例如,如果我想要城市,它们应该按如下方式输出

**New York**
Albany
Buffalo
Syracuse
**California**
San Francisco
Sacramento
Los Angeles

欢迎提出任何建议。

这里有两种awk解决方案。第一种是幼稚和重复的,但更容易遵循和学习。后一种是尝试减少重复

这两种解决方案在处理数据文件中的错误方面都是脆弱的。如果您可以自由选择实现语言,我建议您使用ruby、perl或python之类的语言

保存到一个文件(例如,
showinfo.sh
)并用一个参数“cities”或“colleges”调用以确定模式。此外,您必须将数据文件重定向到stdin

调用示例(对于任一解决方案):

第二种解决方案,消除重复:

#!/bin/bash
set -e
set -u
mode=$1
awk -v mode=$mode '
/begin_/    {st=$1; next} 
/end_/      {st=""; next} 

{ 
  if (st=="begin_state") { sn=$0 }
  else { data[st, sn]=data[st, sn]"\n"$0 }
} 

END {
  for (combo in data) {
    split(combo, sep, SUBSEP);
    type = sep[1];
    state_name = sep[2];
    if (type == "begin_"mode) {
      print "==" state_name "==" data[combo];
    }
  }
}'
使用的输入文件(我注意到它最近在问题中发生了变化):

运行第一个解决方案时的会话:

./showinfo.sh cities < states.txt
./showinfo.sh colleges < states.txt
#!/bin/bash
set -e
set -u
#mode=cities
mode=$1

awk -v mode=$mode '
/begin_state/    {st="states"; next} 
/end_state/      {next} 
/begin_cities/   {st="cities"; next} 
/end_cities/     {next} 
/begin_colleges/ {st="coll"; next} 
/end_colleges/   {next} 

{ 
  if (st=="states") {
    sn=$0; 
  }
  else 
    if (st=="cities") cities[sn]=cities[sn]"\n"$0
    else if (st=="coll") colleges[sn]=colleges[sn]"\n"$0; 
} 

END {
  if (mode=="cities") {
    for (sn in cities) { print "=="sn"=="cities[sn] } ; 
  } 
  else if (mode=="colleges") {
    for (sn in colleges) { print "=="sn"=="colleges[sn] } ; 
  } 
  else { print "set mode either cities or colleges" }
}'
$ bash showinfo.sh cities < states.txt 
==New York==
Albany
Buffalo
Syracuse
==California==
San Francisco
Sacramento
Los Angeles
$bash showinfo.sh cities
在awk中有两种解决方案。第一种是幼稚和重复的,但更容易遵循和学习。后一种是减少重复的尝试

这两种解决方案在处理数据文件中的错误方面都是脆弱的。如果您可以自由选择实现语言,我建议您使用ruby、perl或python之类的语言

保存到一个文件(例如,
showinfo.sh
)并用一个参数“cities”或“colleges”调用以确定模式。此外,您必须将数据文件重定向到stdin

调用示例(对于任一解决方案):

第二种解决方案,消除重复:

#!/bin/bash
set -e
set -u
mode=$1
awk -v mode=$mode '
/begin_/    {st=$1; next} 
/end_/      {st=""; next} 

{ 
  if (st=="begin_state") { sn=$0 }
  else { data[st, sn]=data[st, sn]"\n"$0 }
} 

END {
  for (combo in data) {
    split(combo, sep, SUBSEP);
    type = sep[1];
    state_name = sep[2];
    if (type == "begin_"mode) {
      print "==" state_name "==" data[combo];
    }
  }
}'
使用的输入文件(我注意到它最近在问题中发生了变化):

运行第一个解决方案时的会话:

./showinfo.sh cities < states.txt
./showinfo.sh colleges < states.txt
#!/bin/bash
set -e
set -u
#mode=cities
mode=$1

awk -v mode=$mode '
/begin_state/    {st="states"; next} 
/end_state/      {next} 
/begin_cities/   {st="cities"; next} 
/end_cities/     {next} 
/begin_colleges/ {st="coll"; next} 
/end_colleges/   {next} 

{ 
  if (st=="states") {
    sn=$0; 
  }
  else 
    if (st=="cities") cities[sn]=cities[sn]"\n"$0
    else if (st=="coll") colleges[sn]=colleges[sn]"\n"$0; 
} 

END {
  if (mode=="cities") {
    for (sn in cities) { print "=="sn"=="cities[sn] } ; 
  } 
  else if (mode=="colleges") {
    for (sn in colleges) { print "=="sn"=="colleges[sn] } ; 
  } 
  else { print "set mode either cities or colleges" }
}'
$ bash showinfo.sh cities < states.txt 
==New York==
Albany
Buffalo
Syracuse
==California==
San Francisco
Sacramento
Los Angeles
$bash showinfo.sh cities
Hi,如果是这样的话,将有助于标记它。到目前为止,您尝试了什么?还要注意,您的输入列表至少有两个错误:
end\uuu.state
end cities
。感谢您指出错误。这不是家庭作业问题。我没有在awk中编写它。在excel中尝试了它,但没有多大成功。我只看到了一行stackoverflow.com上的awk代码可以很好地处理单字段过滤问题。(请参阅)在我的问题中,有两对标记:一对标记始终是“州”。第二对标记可以是“城市”或“大学”。因此,我需要始终打印州名,然后打印城市或学院。也可以在州下添加其他字段。您好,如果是这样,将有助于将其标记为州名。您迄今为止尝试了什么?请注意,您的输入列表至少有两个错误:
end\uuu.state
end cities
。感谢您指出t他犯了错误。这不是家庭作业问题。我没有用awk编码。在excel中尝试过,但没有多大成功。我在stackoverflow.com上看到一行awk代码,可以很好地处理单字段筛选问题。(请参阅)在我的问题中,有两对标记:一对始终是“州”。第二对可以是“城市”或“大学”。因此,我需要始终打印州名称,然后打印城市或学院。其他字段也可以添加到州下。如果您使用我描述的示例尝试您的代码,您是否也可以发布您的unix会话副本?非常感谢!-C。谢谢,它确实帮助我澄清了一些问题。我非常感谢您花时间写出这段漂亮的代码。我现在可以在我的文本文件中试用。希望它能帮助其他人处理类似的过滤问题。再次-C@Cyrus当解决方案正是您所需要的时,不要忘记将@Neilb的答案标记为“正确”答案。如果您尝试使用我描述的示例编写代码,可以吗另外,请发布您的unix会话副本?非常感谢!-C。谢谢,它确实帮助我澄清了一些事情。我非常感谢您花时间发布这段漂亮的代码。我现在可以在我的文本文件中试用它。希望它也能帮助其他人处理类似的过滤问题。再次-C@Cyrus当解决方案是正是你需要的,别忘了把@Neilb的答案标记为“正确”答案。