简体   繁体   English

如何在sed中将命令的结果作为字符串参数输入

[英]How to input a command's result as a string argument in sed

i want to execute a command as follows on my bash terminal: 我想在我的bash终端上执行以下命令:

sed -i '6i `sed '1!d' input.in`' out

with which i can insert at line 6 of file out (with replacing -i option) the result of the sed '%1!d' input.in command. 通过它我可以在sed '%1!d' input.in命令的结果的文件输出的第6行插入(替换-i选项)。 I haven't found anything useful, and have tried both `com`, $(com) and com | 我没有发现任何有用的东西,并且尝试了`com`,$(com)和com | sed -i '6i ' out, where com stands for sed '%1!d' input.in . sed sed '%1!d' input.in ,其中com代表sed '%1!d' input.in I don't have any problem changing the syntax of the whole command but i want it to be written in one line on terminal use sed. 我更改整个命令的语法没有任何问题,但是我希望将其写在终端使用sed的一行中。

Thanks for listening, awaiting your answer. 感谢您的收听,等待您的答复。

For EdMorton: 对于EdMorton:

Example Input:

input.in:
into a lake.

out:
Mary was runing around a pond and fell
into a lake.


Mary fell into a what?

Desired Output:
Mary was runing around a pond and fell
into a lake.


Mary fell into a what?
into a lake.

Try using r on standard input instead of i . 尝试在标准输入而不是i上使用r

sed '%1!d' input.in |
sed -i '6r /dev/stdin' out

If your platform doesn't support /dev/stdin or /dev/fd/0 , see if your sed supports - to mean standard input ... or, in the worst case, resort to a temporary file. 如果您的平台不支持/dev/stdin/dev/fd/0 ,请查看您的sed支持-表示标准输入...,或者在最坏的情况下,使用临时文件。

As commenters have already pointed out, %1!d does not appear to be a valid command in most sed dialects, but that is basically unimportant here. 正如评论者已经指出的那样,在大多数sed方言中, %1!d似乎不是有效的命令,但是在此基本上不重要。 (If you mean to print just the first line, maybe you mean sed '1!d' , although sed 'p;q' does that more efficiently.) (如果只打印第一行,则可能是sed '1!d' ,尽管sed 'p;q'更有效。)

sed is for simple substitutions on individual lines, that is all. sed用于单行替换,仅此而已。 For anything else you should be using awk. 对于其他任何事情,您都应该使用awk。

Given this modified input file 给定此修改后的输入文件

$ cat input.in
a Windows folder C:\Windows\Temp

Here is what the sed solution you posted in your comments does: 这是您在评论中发布的sed解决方案的作用:

$ sed '1!d' input.in > temp.of.in && sed "6i `cat temp.of.in`" out
Mary was runing around a pond and fell
into a lake.


Mary fell into a what?
a Windows folder C:WindowsTemp

and here is what an awk solution does more efficiently and accurately and without a temp file: 这是awk解决方案在没有临时文件的情况下可以更有效,更准确地执行的操作:

$ awk 'NR==1{x=$0;nextfile} FNR==6{print x} 1' input.in out
Mary was runing around a pond and fell
into a lake.


Mary fell into a what?
a Windows folder C:\Windows\Temp

Notice the awk solution preserved the path-separator backslashes while the sed one stripped them. 请注意,awd解决方案保留了路径分隔符反斜杠,而sed则将其删除。 Also note that you should really add && rm temp.of.in to the end of your sed command line to clean up the temp file and you should be using $(..) to execute your command, not obsolete backticks. 还要注意,您确实应该在sed命令行的末尾添加&& rm temp.of.in以清理临时文件,并且应该使用$(..)执行命令,而不要使用过时的反引号。

The awk solution uses GNU awk for ;nextfile , with other awks you'd replace that with }NR==FNR{next or similar but since you are using GNU sed I assume you have GNU awk too. awk解决方案对;nextfile使用GNU awk,对于其他awks,您可以将其替换为}NR==FNR{next或类似名称,但由于您使用的是GNU sed,所以我也假设您也有GNU awk。

Note that if you DID have a burning desire to use sed and accept it won't exactly reproduce the input, there are simpler, more efficient ways to do what your current script does, eg: 请注意,如果您对DID渴望使用sed并接受它并不能完全重现输入,那么可以使用更简单,更有效的方法来执行当前脚本的操作,例如:

sed "6i $(head -1 input.in)" out

or even your original idea, just rewritten to remove the obsolete backticks and negative logic of 1!d : 甚至是您最初的想法,只需重写一下即可消除过时的反引号和1!d否定逻辑:

sed "6i $(sed -n '1p' input.in)" out

But seriously - just use awk. 但是请认真使用-只需使用awk。 For anything other than simple substitutions on individual lines it's much more robust, efficient, clear, portable, extensible, etc. etc. than sed. 除了在单个行上进行简单替换以外,其他任何事情都比sed健壮,高效,清晰,可移植,可扩展等。

EDIT To address the questions in your comments: 编辑以解决您的评论中的问题:

  1. Can you explain the arguments on awk. 您能解释一下awk上的参数吗? There are no arguments, just a script that says: If this is the first line read from the first file save it in variable x then move on to the next file. 没有参数,只有一个脚本说:如果这是从第一个文件读取的第一行,请将其保存在变量x中,然后移至下一个文件。 If this is line 6 of the 2nd file print the contents of variable x. 如果这是第二个文件的第6行,则打印变量x的内容。 For every line of the 2nd file, print it (the 1 is idiomatic but a bit tricky at first glance - it's a true condition so it invokes the default action of printing the current input, equivalent to just writing {print} . 对于第二个文件的每一行,打印它( 1是惯用但乍一看有点棘手-这是一个真正的条件,因此调用打印当前输入的默认操作,相当于只是写{print}
  2. how can i replace the out file with the output (without using '>') as the option -i does on sed and avoid printing it to stdout? 我如何将输出文件替换为out文件(不使用'>'),如选项-i在sed上所做的,并避免将其打印到stdout? Just like GNU sed has -i , GNU awk has -i inplace . 就像GNU sed has -i ,GNU awk has -i inplace Be careful though because, just like with sed, it applies to every input file so if you don't print the contents of the first file then when the script is done the first file will be empty. 但是要小心,因为与sed一样,它适用于每个输入文件,因此,如果您不打印第一个文件的内容,那么当脚本完成后,第一个文件将为空。 There's various was to deal with that, including simply printing the lines from file 1 or turning inplace editing on/off in BEGINFILE/ENDFILE blocks, see https://www.gnu.org/software/gawk/manual/gawk.html#Extension-Sample-Inplace , but IMHO awk 'script' file1 file2 > temp && mv temp file2 is the simplest and clearest as well as being portable to all awks/seds/whatever. 有多种处理方法,包括简单地打印文件1中的行或在BEGINFILE / ENDFILE块中打开/关闭就地编辑,请参阅https://www.gnu.org/software/gawk/manual/gawk.html# Extension-Sample-Inplace ,但是恕我直言, awk'script'file1 awk 'script' file1 file2 > temp && mv temp file2是最简单和最清晰的,并且可移植到所有awk / seds /任何地方。
  3. Also if there is a multiline solution like "take lines 1 to 4" from "input.in" and drop them on line 6 of "out"? 另外,是否有一个多行解决方案,例如从“ input.in”中取出“第1至4行”,并将其放在“ out”的第6行中? No problem: 没问题:

.

awk '
    NR==FNR { if (NR<=4) x=x $0 ORS; else nextfile }
    FNR==6 { printf "%s", x }
    { print }
' input.in out

I changed the 1 from the previous script to { print } for clarity. 为了清楚起见,我将前一个脚本的1更改为{ print }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM