就像如何执行多个“sed”命令(由“;”分隔)一样,您可以使用“awk -F”来执行此操作吗?它适用于多个“awk”,但不适用于“awk-F”

Nic*_*ine -2 awk text-processing

您可以通过使用(谢谢家伙\xe2\x80\xa6)分隔cmd来多次调用sed,而无需使用多个管道,;有没有办法将其用于多个awk -Fcmd?

\n

使用sed多个管道

\n
\necho "\'text\';" | \\\nsed s"#\';##"g  | \\ \nsed s"#\'##"g   \n\ntext\n
Run Code Online (Sandbox Code Playgroud)\n

使用sedwith;作为分隔符

\n
\necho "\'text\';" | \\\nsed "            \\\n  s#\';##g;       \\\n  s#\'##g         \\\n"\n\ntext\n
Run Code Online (Sandbox Code Playgroud)\n

编辑:

\n

因此,您可以使用 加入多个awkcmd ;。但不能对多个awk -Fcmd执行此操作

\n

问题是关于串联多个 awk -F命令,这仍然没有答案。

\n

背景

\n
\n# \'/x/ gives the href of the actual videos\n# awk -F \'/x/\' \'{print$2}\xe2\x80\x99 \n# because the /x/ is unique to the video urls\n# after this the video links appear\n# but I have to get rid of stuff \n# on the right of them so I do \n# awk \xe2\x80\x94F \'title\' \'{print$1}\' \n# this returns all the video links \n# but they have a double quotes \n# and a semi colon on the end.\n\ncurl -s                                 \\\n  https://site.com/plist/page={0..50} | \\\ngrep \'/x/\'                            | \\\nawk -F \'/x/\' \'{print$2}\'              | \\\nawk -F \'title\' \'{print$1}\'            | \\\nsed \'                                   \\\n  s#";##g;                              \\\n  s#"##g                                \\\n\'\n
Run Code Online (Sandbox Code Playgroud)\n

所以现在我有一堆视频链接并进行进一步处理以获得视频下载链接,然后我使用mapfile将下载链接获取到数组中并用于parallel下载它们。

\n

我缩短了在该代码示例中实际执行的许多内容。

\n

编辑:

\n

所以\xe2\x80\x99无法完成。非常感谢该用户。

\n

该用户评论说用于sed我的一个特定案例,这将消除需要,awk -F但我至少还有 20 个其他案例。但它给了我一些思考,我这样做的原因,awk -F是因为它在不了解任何 sed 正则表达式的情况下为我提供了我需要的东西。

\n

不管怎样,谢谢大家,我想知道它是否可以完成,它可以\xe2\x80\x99t,所以我\xe2\x80\x99m满意。

\n

谢谢

\n

对于@St\xc3\xa8phaneChazelas,他们的评论解决了我的问题。

\n

Adm*_*Bee 11

更新:这个答案发布后,问题发生了很大的变化,所以原来的答案——虽然仍然正确——对解决OP的实际问题没有多大帮助。

\n

您似乎尝试处理curl表单的输出

\n
Ignore this\nhttp://some.url.involving/x/\'video-link-1\';title...\nhttp://some.url.involving/x/\'video-link-2\';title...\nIgnore that\n
Run Code Online (Sandbox Code Playgroud)\n

等等,你想去的地方

\n
    \n
  1. 仅处理出现的行/x/,并且
  2. \n
  3. 提取中间的部分\' ... \'
  4. \n
\n

最简单的方法是仅使用一个字段分隔符,即\'

\n
curl -s https://site.com/plist/page={0..50} | awk -F"\'" \'/\\/x\\//{print $2}\'\n
Run Code Online (Sandbox Code Playgroud)\n

此外,这将仅考虑包含该/x/模式的行。因此,对于上面的例子,输出将是

\n
video-link-1\nvideo-link-2\n
Run Code Online (Sandbox Code Playgroud)\n

如果您想通过更改字段分隔符来进行拆分,您当然可以按照 St\xc3\xa9phane Chazelas 的答案FS中所示中途更改内部变量。但是,在这种情况下,我宁愿使用这样一个事实:多字符字段分隔符,无论是通过作为选项参数设置还是通过程序内部的赋值设置,都被视为完整的正则表达式。-FFSawk

\n

这意味着您可以使用“或”类型替代作为字段分隔符来涵盖两种情况(但您还应该包括单引号和分号以避免进一步的后处理需要):

\n
curl -s https://site.com/plist/page={0..50} |\n   awk -F\'/x/\\047|\\047;title\' \'/\\/x\\//{print $2}\'\n
Run Code Online (Sandbox Code Playgroud)\n
    \n
  • 这会将字段分隔符设置为 /x/\' \';title
  • \n
  • 它只会考虑包含该/x/模式的行。在这些行上,它将打印第二个字段,这是您想要的信息(并且已经删除了 和\';
  • \n
  • 单引号表示为 ASCII 代码,\\047以避免出现“单引号内的单引号”问题(我假设您的操作系统是基于 ASCII 的系统,而不是EBCDIC)。
  • \n
\n
\n

经常遇到的另一种方法是“仅用有趣的部分替换整行”,如

\n
curl -s https://site.com/plist/page={0..50} |\n   awk \'/\\/x\\//{print gensub(/.*\\/x\\/\\047([^\\047]+).*/,"\\\\1","1")}\'\n
Run Code Online (Sandbox Code Playgroud)\n

这将再次仅考虑模式/x/出现的行,用遵循该模式的单引号之间的内容替换整行,并打印修改后的行以仅提取该部分。

\n

单个sed调用也可以实现同样的效果,尽管通过 ASCII 代码表示单引号在这里不起作用,因此涉及的内容更多一些。假设 GNU具有 ERE 选项sed-E

\n
curl -s https://site.com/plist/page={0..50} | sed -n -E \'s|.*\\/x\\/\'\\\'\'([^\'\\\'\']+).*|\\1|p\'\n
Run Code Online (Sandbox Code Playgroud)\n

默认情况下,这将抑制输出-n,像本例一样执行替换,并且仅在进行替换时才awk打印(尾随p),这意味着找到了模式。/x/\'video-link\';title

\n
\n

原答案如下

\n

框架挑战:有必要吗?

\n

在 中awk,您可以根据需要多次重复同一程序中的任何修改命令,如

\n
echo "\'text\';" | awk \'{gsub(/\\047;/,""); gsub(/\\047/,"")} 1\'\n
Run Code Online (Sandbox Code Playgroud)\n

或者

\n
echo "\'text\';" | awk \'{gsub(/\\047;/,"")} {gsub(/\\047/,"")} 1\'\n
Run Code Online (Sandbox Code Playgroud)\n

(用于\\047在单引号程序中表达单引号)。

\n

你也可以用一种易于阅读的方式写下来,比如

\n
echo "\'text\';" |\n  awk \'{gsub(/\\047;/,"")};\n       {gsub(/\\047/,"")}; 1\'\n
Run Code Online (Sandbox Code Playgroud)\n

或作为专用程序:

\n
echo "\'text\';" | awk -f multi-substitute.awk\n
Run Code Online (Sandbox Code Playgroud)\n

看起来multi-substitute.awk

\n
echo "\'text\';" | awk \'{gsub(/\\047;/,""); gsub(/\\047/,"")} 1\'\n
Run Code Online (Sandbox Code Playgroud)\n

  • @Nickotine 嗯,没问题,没有难受的感觉。但请记住,这是一个“单行”`awk` 程序,它取代了整个管道链 - 在大多数情况下效率低得多,并且可能以意想不到的(乍一看无法解释的)方式失败 - 所以程序不仅仅是删除单引号和分号,它还从整行中提取您感兴趣的字符串。 (2认同)

Sté*_*las 8

有什么问题:

echo "'text';" | sed "
  s/';//g
  s/'//g
"
Run Code Online (Sandbox Code Playgroud)

或者:

awk -v q="'" '
  {
    gsub(q ";", "")
    gsub(q, "")
    print
  }'
Run Code Online (Sandbox Code Playgroud)

或者:

awk -v q="'" '
  {
    gsub(q ";", "")
  }
  {
    gsub(q, "")
  }
  {
    print
  }'
Run Code Online (Sandbox Code Playgroud)

对于这个问题?

不需要几个-es。也许除了 (t)csh 是 PITA 之外,大多数 shell 都可以完全满足您输入多行参数的要求。

-e arginsed实际上指定为在代码中添加换行符argsed因此

sed -e foo -e bar
Run Code Online (Sandbox Code Playgroud)

意味着与

sed 'foo
bar'
Run Code Online (Sandbox Code Playgroud)

没有什么可以阻止你也做:

NL='
' # or NL=$'\n' with most modern shells.

sed_cmd1='s/foo/bar' awk_cmd1='gsub(/foo/, "bar")'
sed_cmd2='s/bar/baz' awk_cmd2='gsub(/bar/, "baz")'

sed "$sed_cmd1$NL$sed_cmd2"
# or
awk "{$awk_cmd1$NL$awk_cmd2${NL}print}"
Run Code Online (Sandbox Code Playgroud)

或者:

awk "$(printf '%s\n' '{gsub("foo", "bar"}' '{gsub("bar", "baz")}')"
Run Code Online (Sandbox Code Playgroud)

awk语法上,您可以用 with 替换换行符来分隔命令;。也可以sed,但仅在有限数量的命令之后(不在wr:acibt}#s命令之后,如果w例如使用了标志,至少是可移植的)。

为了避免担心引用,您还可以这样做:

awk "$(<<'EOF' cat
  {
    gsub("';", "") # ' " \ not a problem
    gsub("'", "")
    print
  }
EOF
)"
Run Code Online (Sandbox Code Playgroud)

或者在大多数系统上:

awk -f /dev/fd/3 3<<'EOF'
  {
    gsub("';", "") # ' " \ not a problem
    gsub("'", "")
    print
  }
EOF
Run Code Online (Sandbox Code Playgroud)

(请注意第一个周围的引号,EOF以确保此处文档中的 shell 不会执行任何扩展)


至于您对多个-Fs 的编辑(不要与 混淆-f):

-F x是将字段分隔符设置为x,与-v FS=x或添加一个BEGIN { FS = "x" }.

例如,这样做-F ' ' -F '|' -F ','不会帮助您获得第二个空格,分隔字段的第三个|分隔字段的第一个分隔字段。foo a|b|x,y,z|c bar那只会设置FS,.

为此你需要:

awk '
  {
    split($0, a, " ")
    split(a[2], b, "|")
    split(b[3], c, ",")
    print c[1]
  }'
Run Code Online (Sandbox Code Playgroud)

或者使用FS

awk '
  {
    FS = " "; $0 = $2
    FS = "|"; $0 = $3
    FS = ","; print $1
  }'
Run Code Online (Sandbox Code Playgroud)

FS这里使用where来在访问(x >= 1)$0时分割(最初是当前记录的内容) 。$x

IOW,能够减少

awk '{print "something out of "$0}' |
  awk '{print "something out of "$0" as modified by the first}'
Run Code Online (Sandbox Code Playgroud)

你需要:

awk '
  {
    $0 = "something out of "$0
    print "something out of "$0" as modified by the first
  }'
Run Code Online (Sandbox Code Playgroud)

您可以轻松地减少两个seds 各做一个s/x/y/或相当于两个awks 做{gsub("x", "y"); print},但您不一定对任何sedawk代码应用相同的配方,您只需要了解它们如何工作以及它们一次处理一条记录当文本流进来时。


Red*_*ick 5

sed-e

echo "'text';" | sed s"#';##"g  | sed s"#'##"g  
text

echo "'text';" | sed -e s"#';##"g -e s"#'##"g  
text
Run Code Online (Sandbox Code Playgroud)

通常不需要使用多个命令,也不需要使用-e两次(只需使用分号)。允许 awk 或 sed 的单个实例处理这两项操作可能会更快。

echo "'text';" | sed s"#';##"g  | sed s"#'##"g  
text

echo "'text';" | sed -e s"#';##"g -e s"#'##"g  
text
Run Code Online (Sandbox Code Playgroud)

我可能已经使用捕获来完成此操作

$ echo "'text';" | sed "s/';//g; s/'//g"
text
Run Code Online (Sandbox Code Playgroud)

当然,我毫不怀疑您的简单示例是一对无法以这种方式轻松组合的程序的占位符。不过我不希望新手有错误的印象。简单的操作最好以这种方式组合起来。


awk-F

curl -s                                 \
  https://site.com/plist/page={0..50} | \
grep '/x/'                            | \
awk -F '/x/' '{print$2}'              | \
awk -F 'title' '{print$1}'            | \
sed '                                   \
  s#";##g;                              \
  s#"##g                                \
'
Run Code Online (Sandbox Code Playgroud)

对于 AWK,正如其他人指出的那样,与其尝试为不同的表达式设置不同的字段分隔符,不如完全使用不同的方法。如果正则表达式可以充分表达要遇到的所有数据的结构,那么这可能是从具有混合分隔符的字符串中提取项目的最佳方法。正则表达式经常被过度使用,但它们不应该被忽视。

鉴于此数据:

$ echo "'text';" | sed -r "s/'([^']*)';/\1/g"
text
Run Code Online (Sandbox Code Playgroud)

我可能会尝试在 Perl 中完成上述全部任务

curl -s                                 \
  https://site.com/plist/page={0..50} | \
grep '/x/'                            | \
awk -F '/x/' '{print$2}'              | \
awk -F 'title' '{print$1}'            | \
sed '                                   \
  s#";##g;                              \
  s#"##g                                \
'
Run Code Online (Sandbox Code Playgroud)

使用 Curl 和单个 AWK 程序可能可以轻松完成此操作。我不是 AWK 专家,但我可能会从以下内容开始并完善它

$ cat /tmp/titles.txt
preamble
p/q/r/s/title"Not This";Brick
something
a/x/b/c/title"The Rime of the Ancient Mariner";Coleridge
otherthing
f/g/x/h/title"Jackass";Knoxville
remainder
Run Code Online (Sandbox Code Playgroud)

(Gnu Sed 4.2.2、Perl 5.18.2。Gnu AWK 4.0.1)