【问题标题】:How can I use sed to generate an awk file?如何使用 sed 生成 awk 文件?
【发布时间】:2019-12-18 22:36:42
【问题描述】:

如何编写 sed 命令来生成 awk 文件。

这是我的问题: 例如,我有一个文本文件 A.txt,其中每行包含一个单词。

app#
#ple
#ol#

# 表示单词何时开始/结束/开始和结束。例如,app# 显示单词以“app”开头。 #ple 表示单词以“ple”结尾。 #ol# 表示单词中间有“ol”。

我必须从 sed 命令生成一个 awk 文件,该文件读取另一个文件 B.txt(每行包含一个单词)并递增变量 start、end、middle。

我如何编写 sed 命令,从而为文本文件 A.txt 中的每一行生成一个 awk 代码,即。

{ {if ($1 ~/^app/)
    {start++;}
}

例如,如果我将带有这些单词的另一个文件 B.txt 输入到 awk 脚本中,

application
people
bold
cold

输出将是;开始 = 1,结束 = 1,中间 = 2。

【问题讨论】:

  • 为什么专注于sed生成awk代码?这一切都可以在 awk 中完成。
  • @glennjackman 问题来自我们的教程课程,但他没有讨论答案。您对如何实现 sed 代码有任何提示吗?
  • @llamaro25 如果您显示您自己尝试过的sed 命令会有所帮助
  • @Sundeep 我不知道从哪里开始。这就是我寻求帮助的原因。我已经阅读了关于 sed 的教程,但没有一篇适合我在这里所做的描述。

标签: awk sed


【解决方案1】:

在我的脑海中,未经测试:

/\(.*\)#$/s//{if ($1 ~ /^\1/) start++; next}/
/#\(.*\)$/s//{if ($1 ~ /\1$/) end++; next}/
/\(.*\)/s//{if ($1 ~ /\1/) middle++; next}/

构造\(.*\) 匹配任何文本并将其保存在反向引用中,然后\1 调用反向引用。 s 命令后面的空模式指的是与该行匹配的模式。 next 防止在其他两个模式之一已经匹配后匹配第三个模式。

【讨论】:

  • 通过检查和未经测试,我认为这将超过。你需要更多的'^'和'$'。
【解决方案2】:

实际上,我会使用ed 而不是sed。

从A.txt 创建A.awk 并在B.txt 上运行的快速脚本:

#!/bin/sh

ed -s A.txt <<'EOF'
1,$ s!^#\(.*\)#$!$0 ~ /.+\1.+/ { middle++ }!
1,$ s!^#\(.*\)!$0 ~ /\1$/ { end++ }!
1,$ s!^\(.*\)#!$0 ~ /^\1/ { start++ }!
0 a
#!/usr/bin/awk -f
BEGIN { start = end = middle = 0 }
.
$ a
END { printf "start = %d, end = %d, middle = %d\n", start, end, middle }
.
w A.awk
EOF

# awk -f A.awk B.txt would work too, but this demonstrates a self-contained awk script
chmod +x A.awk
./A.awk B.txt

运行它:

$ ./translate.sh
start = 1, end = 1, middle = 2
$ cat A.awk
#!/usr/bin/awk -f
BEGIN { start = end = middle = 0 }
$0 ~ /^app/ { start++ }
$0 ~ /ple$/ { end++ }
$0 ~ /.+ol.+/ { middle++ }
END { printf "start = %d, end = %d, middle = %d\n", start, end, middle }

注意:这假设中间的模式不应该在一行的开头或结尾匹配。


但是这里尝试使用 sed 创建 A.awk,将所有 sed 命令放在一个文件中,因为尝试使用 -e 将其作为单线器并正确地进行所有转义并不是我想要的目前:

makeA.sed的内容:

s!^#\(.*\)#$!$0 ~ /.+\1.+/ { middle++ }!
s!^#\(.*\)!$0 ~ /\1$/ { end++ }!
s!^\(.*\)#!$0 ~ /^\1/ { start++ }!
1 i\
#!/usr/bin/awk -f\
BEGIN { start = end = middle = 0 }
$ a\
END { printf "start = %d, end = %d, middle = %d\\n", start, end, middle }

运行它:

$ sed -f makeA.sed A.txt > A.awk
$ awk -f A.awk B.txt
start = 1, end = 1, middle = 2

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多