两个参数日期之间的输出行包括第一个参数日期但不包括第二个参数日期

两个参数日期之间的输出行包括第一个参数日期但不包括第二个参数日期

这个问题之前已经被问过,除了他们正在寻找两个日期之间的文本(包括或排除这些日期)。我更改了其中一个答案,以便它选择并包含第一个日期并转到但排除第二个日期(我认为/希望)。但是我不明白您在哪里提供了要应用此内容的文本文件?

set - date1 date2 "junk"  

from="$1"
till="$2"
file="$3"  

# Output lines between two parameter dates 
# INCLUDING the first parameter date but not the second

awk -v from=$from -v till=$till '
    ($2 >= from) && ($2 < till) { print $0 ; next }
    ($2 >= till) { exit }' "$file"

自从发现了一个笨拙的解决方案后,我意识到还有另一个方面可以改进这一点,并防止我多次编写脚本行的细微更改。

目前的工作解决方案是:

awk '/^date_1_/,/^date_2_/ {print}' file.txt > file2.txt
grep -v "date_2_" file2.txt > file2tmp.txt
mv file2tmp.txt file2.txt

不过我希望它对每个新日期都这样做。例如,从Date_1_(包括date_1_)到Date_2_(但不包括Date_2_)选择文本,然后以同样的方式选择从Date_2_到3的文本,以同样的方式选择3到4(一直到1000)。有没有可以轻松扩展的解决方案?

输入文本文件示例(虽然实际文件最多为 1000,txt 文件中的下划线之间也没有空格,但我没有反勾来逃避斜体效果):

' > _ 1_ fe fi fo fum >_ 2_ beep bap bop >_ 3_ ti fi at at

示例输出:
创建的文本文件 1: > _ 1_ fe fi fo fum
创建的文本文件 2: >_ 2_ beep bap bop
创建的文本文件 3: >_ 3_ ti fi at at

答案1

如果我正确理解这个不断变化的问题的当前状态,您有一个具有任意行数的文件,分为由类似 to 标记的部分_1__1000_并且您希望将这些部分拆分为单独的文件。如果是这样,那么csplit可以这样做:

 csplit file.txt '/^_[0-9]\+_/' '{*}'

答案2

awk程序将通过一个命令完成您最初想做的事情:

awk '/^date_1_/,/^date_2_/ { if (prev) print prev ; prev=$0 }' file.txt > file2.txt

你测试了这个,它有效。然后,您扩展了问题,以便能够对作为参数对给出的一系列通用行标记进行操作。

您可以通过定义 2 个辅助函数来为此创建一个舒适的工作流程:

  • 创建 awk 程序以通过进程替换输入
  • 另一个运行 awk,并将参数传递给第一个助手:

代码:

fun1(){ while [ ! -z $1 ] && [ ! -z $2 ] ; do echo "
/^$1/,/^$2/ {if (\$0~/^$1/) prev=\"\";
if (prev) print prev; prev=\$0 }"; shift; shift ; done }

fun2(){ awk -f <(fun1 $@); }

# Example data, example ranges, but could be any string:
seq 1 13 | sed -e 's/.*/_&_/' | fun2 _2 _4 _9 _11
_2_
_3_
_9_
_10_

问题版本 3 的解决方案:

fun3(){ echo "/^$1/,/^$2/ {if (\$0~/^$1/) prev=\"\";
if (prev) print prev; prev=\$0 }"; }

fun4(){ ifile=$1; shift; while [ ! -z $1 ] && [ ! -z $2 ] ; do
        awk -f <(fun3 $1 $2) $ifile > $1.txt ; shift; done }

# Create example data file:
seq 1 13 | sed -e 's/.*/_&_/' > inputData.txt

fun4 inputData.txt _2 _5 _8 _12

ls _*
_2.txt  _5.txt  _8.txt

答案3

我做了更多的阅读,并将一些东西拼凑在一起,这现在对我有用。

awk '/^date_1_/,/^date_2_/ {print}' file.txt > file2.txt
grep -v "date_2_" file2.txt > file2tmp.txt
mv file2tmp.txt file2.txt

但它仍然需要 2 个步骤和一个临时文件。

相关内容