如何在linux shell下获取引用另一个文件的每个创建表的第n个字段?
我有两个文本文件:file1.txt和file2.txt。 file1.txt是一个索引文件,例如file1.txt的内容:如何在linux shell下获取引用另一个文件的每个创建表的第n个字段?,linux,awk,sed,grep,text-processing,Linux,Awk,Sed,Grep,Text Processing,我有两个文本文件:file1.txt和file2.txt。 file1.txt是一个索引文件,例如file1.txt的内容: abc 1 def 2 ghi 3 其中“abc 1”是指表“abc”中的第一个字段 file2.txt实际上是许多表的create table命令的转储,例如file2.txt的内容: create table "def".something ( f01 char(10), f02 char(10), f03 char(10),
abc 1
def 2
ghi 3
其中“abc 1”是指表“abc”中的第一个字段
file2.txt实际上是许多表的create table命令的转储,例如file2.txt的内容:
create table "def".something
(
f01 char(10),
f02 char(10),
f03 char(10),
f04 date
);
create table "abc".something
(
x01 char(10),
x02 char(1),
x03 char(10),
);
create table "ghi".something
(
z01 char(10),
z02 intr(10),
z03 double(10),
z04 char(10),
z05 char(10),
);
我想根据file1.txt中的每一行“mn”,通过在Linux shell下仅使用或组合使用awk、grep、sed或任何文本处理命令,获得file.txt中表m的第n个字段的列表。关于上述示例,输出预计为:
abc,x01 char(10)
def,f02 char(10)
ghi,z03 double(10)
有可能吗?我该怎么做?这是您的脚本:
while read line
do set $line
i=$(($2+1))
echo "$1,`grep -A$i "$1" file2.txt | tail -1`"
done < file1.txt
读取行时
不要设置$line
i=$($2+1))
echo“$1,`grep-A$i”$1“file2.txt | tail-1”
完成
当前输出在第二列中有前导空格和尾随逗号。您可以使用我留给您作为家庭作业的sed
删除它们
该脚本的工作原理如下:
- 逐行读取文件1
- 使用
将行拆分为字段set
- 增量
,这是必需的,因为每个$2
行后都会出现创建
)(
- 在第二个文件中查找模式
,其上下文由$1
$2
- 将grep输出附加到
&$1
,
- 这是您的脚本:
while read line
do set $line
i=$(($2+1))
echo "$1,`grep -A$i "$1" file2.txt | tail -1`"
done < file1.txt
读取行时
不要设置$line
i=$($2+1))
echo“$1,`grep-A$i”$1“file2.txt | tail-1”
完成
当前输出在第二列中有前导空格和尾随逗号。您可以使用我留给您作为家庭作业的sed
删除它们
该脚本的工作原理如下:
- 逐行读取文件1
- 使用
将行拆分为字段set
- 增量
,这是必需的,因为每个$2
行后都会出现创建
)(
- 在第二个文件中查找模式
,其上下文由$1
$2
- 将grep输出附加到
&$1
,
awk -F'[ "]' '
FNR==NR{file1[$1] = $2; next}
$4 in file1{counter = file1[$4] + 1; table = $4};
!counter{print table,$0}
'
测试
$ awk -F'[ \"]' 'FNR==NR{file1[$1] = $2; next} $4 in file1{counter = file1[$4] + 1; table = $4}; !counter--{print table,$0} ' file1 file2
def f02 char(10),
abc x01 char(10),
ghi z03 double(10),
您可以按以下方式编写awk脚本:
awk -F'[ "]' '
FNR==NR{file1[$1] = $2; next}
$4 in file1{counter = file1[$4] + 1; table = $4};
!counter{print table,$0}
'
测试
$ awk -F'[ \"]' 'FNR==NR{file1[$1] = $2; next} $4 in file1{counter = file1[$4] + 1; table = $4}; !counter--{print table,$0} ' file1 file2
def f02 char(10),
abc x01 char(10),
ghi z03 double(10),
第一个解决方案:
此解决方案按定义文件中的顺序报告所需字段。这与请求的输出不同,请求的输出以索引顺序显示这些字段;这在第二个解决方案中有所介绍
另一个未涉及的要求是索引可能有多个条目用于相同的数据库名称,提取多个字段。第二个解决方案也涉及到这一点
运行:
获取字段号的诀窍是使用行
指令匹配数据库标题后面的当前行号,将行号捕获到开始
变量中:@(开始行)
。@(跳过)
指令然后跳过零行或多行输入,直到后续的材质匹配:该材质调用另一个行
匹配,但这次使用Lisp表达式的值(+start[fnum name]-1)
:基于1的字段的行号相对于先前在开始
中捕获的行号
这种类型的TXR解决方案表示与数据的关键功能相匹配,而不是盲目依赖固定偏移量和最小正则表达式。TXR最大限度地减少了因格式已更改而成为垃圾的数据获得成功输出的机会。但与此同时,人们对从显然,@table@field
收集空格分隔的对,并且
create table "@name".something
(
匹配数据中的特定“图片”等等
(顺便说一句,这个文字“something”可能应该被一个变量替换!但是样本数据没有显示这种差异。)
TXR中的第二种解决方案:
在这里,我们对索引做了一个小改动,从abc
中选择两个字段:
$ cat index
abc 1
def 2
abc 2
ghi 3
代码现在是:
@(do
(defvarl dblist)
(defvarl dbhash (hash :equal-based))
(defstruct dbfield nil
tblname fieldno defn
(:postinit (self)
(push self dblist)
(set [dbhash self] self))
(:method equal (self) (list self.tblname self.fieldno))))
@(repeat)
@tblname @field
@ (do (new dbfield
tblname tblname
fieldno (int-str field)))
@(end)
@(next)
@(repeat)
create table "@tblname".@suffix
(
@ (bind fieldno 0)
@ (repeat)
@defn,
@ (do (whenlet ((dbrec [dbhash (list tblname (inc fieldno))]))
(set dbrec.defn defn)))
@ (until)
);
@ (end)
@(end)
@(output)
@ (repeat :vars ((dbf (keep-if (usl defn) (reverse dblist)))))
@{dbf.tblname},@{dbf.defn}
@ (end)
@(end)
数据结构与一点OOP一起使用。当扫描第一个文件时,它使用new
宏运算符将对转换为dbfield
类型的结构对象。这些对象有一个表名和一个整数记录号。它们还有一个定义(defn
slot)新创建时,它们的:postinit
处理程序将它们添加到全局列表dblist
,并将每个记录添加到全局哈希dbhash
。equal
方法确保为了equal
相等,记录减少到两个el由表名和字段号组成的索引列表。这就是哈希表的有效索引
当我们处理第二个文件时,我们使用数据库名称和运行计数器来查看dbfield
中的键是否存在dbhash
结构。如果存在,我们使用提取的定义更新该记录defn
在@(output)
部分中,我们指示repeat在dblist
上迭代,但相反(因为第一个文件的条目像堆栈一样被推到它上面)。我们还将此列表仅筛选那些具有不是nil
的defn
插槽的条目。也就是说,索引文件可以引用不存在的数据库和字段。可以扩展要求以某种方式报告这些条目或引发错误。中的第一个解决方案:
此解决方案按定义文件的顺序将必填字段报告为定义文件中出现的字段。这与第二个解决方案中包含的按索引顺序排列的请求输出不同。