我想读取29个文件中的行并处理这些行并将它们放入if语句中。
在这个例子中,我创建了3个示例文件和一个shell脚本文件,它基本上使用while循环读取文件并从每个文件中读取这些行并使用带有if语句的sed处理,此if语句用于检查以查看第一个所有文件中的变量(例如abc.def)并将它们的值复制到文件中。
示例:
a.txt
abc.def=123
efg.hij=45666
kml.nop=789
qrs.tuv=901
wxy.zabc=234
b.txt
abc.def=123
efg.hij=45666
kml.nop=897
klm.nop=123
qrs.tuv=901
wxy.zabc=234
c.txt
abc.def=12344
efg.hij=456
kml.nop=123
klm.nop=789
wxy.zabc=234
sprict.sh
#!/bash/bin
count=1
while IFS= read -r lineA && IFS= read -r lineB <&3 && IFS= read -r lineC <&4; do
#splitting the line into two,example from line abc.def=123 slit varaibles as "abc.def" and "123"
A1=`echo "$lineA" | sed -e 's/\=\(.*\)//' `
A2=`echo "$lineA" | sed -e 's/^[^=]*=//' `
B1=`echo "$lineB" | sed -e 's/\=\(.*\)//' `
B2=`echo "$lineB" | sed -e 's/^[^=]*=//' `
C1=`echo "$lineC" | sed -e 's/\=\(.*\)//' `
C2=`echo "$lineC" | sed -e 's/^[^=]*=//' `
if [ [ "$A1" = "$B1" && "$A1" = "$C1"]];then
echo -e "<variable id=\"$A1\">\t
<a2>"$A2"</a2>\t
<b2>"$B2"</b2>\t
<c2>"$C2"</c2>\t
</variable>\n" >> common.txt
fi
done <a.txt 3<b.txt 4<c.txt
预期输出为:
<variable id="abc.def">
<a2>123</a2>
<b2>123</b2>
<c2>12344</c2>
</variable>
<variable id="efg.hij">
<a2>456</a2>
<b2>45666</b2>
<c2>45666</c2>
</variable>
<variable id="kml.nop">
<a2>789</a2>
<b2>897</b2>
<c2>123</c2>
</variable>
答案 0 :(得分:3)
您可以使用read
来简化将每一行拆分为名称和值,并使用预先构建的模板printf
来简化输出。此外,您的if
语句中存在一些语法错误:空格很重要。
shell保留大于10的文件描述符供自己使用,因此对于29个输入文件,您的方法无法很好地扩展。在bash
4.1及更高版本中,您可以让bash
分配文件描述符。
#!/bash/bin
# Redirect from each input file, using bash-assigned file descriptors
exec {afile}<a.txt
exec {bfile}<b.txt
exec {cfile}<c.txt
template='<variable="%s">\n\t<a2>%s</a2>\n\t<b2>%s</b2>\n\t<c2>%s</c2>\n</variable>\n'
while IFS="=" read -r -u "$afile" A1 A2 &&
IFS="=" read -r -u "$bfile" B1 B2 &&
IFS="=" read -r -u "$cfile" C1 C2; do
if [[ "$A1" = "$B1" && "$A1" = "$C1" ]]; then
printf "$template" "$A1" "$A2" "$B2" "$C2"
fi
done
答案 1 :(得分:3)
下面比较任意数量的文件,并且不要求它们的内容有序(正如chepner给出的解决方案所做的那样)。它还使用XMLStarlet生成XML格式的输出,保证良好的格式。
这确实意味着需要在您的系统上安装XMLStarlet;它通常可用于现代主要操作系统的打包。
#!/bin/bash
join_files() {
local first
if (( $# == 1 )); then
sort <"$1"
elif (( $# == 2 )); then
join -t= <(sort <"$1") <(sort <"$2")
elif (( $# > 2 )); then
first=$1; shift
join -t= <(sort <"$first") <(join_files "$@")
fi
}
main() {
declare -a items
{
printf '%s\n' '(root'
while IFS='=' read -r -a items; do
set -- "${items[@]}"
name=$1; shift
printf '%s\n' '(variable' "Aid $name"
item_num=1
for item; do
printf '%s\n' "(a$item_num" "-$item" ")a$item_num"
(( item_num++ ))
done
printf '%s\n' ')variable'
done < <(join_files "$@")
printf '%s\n' ')root'
} | xmlstarlet depyx | xmlstarlet fo
}
main a.txt b.txt c.txt
答案 2 :(得分:2)
如果您不介意除 bash 之外的其他语言,我可以建议 awk (因为我熟悉它,也因为它很好用文本处理)。这是我的 awk 解决方案,我称之为 text2xml.awk :
BEGIN {
FS="=" # Use the equal sign as field separator
}
# When we encounter a new file, establish a new tag based on the file
# name
# tag: tag names, (a2, b2, c2, ...)
# tagfound: keep track of which tag has been found
# tags: array of tag names, where tags[0] = "a2", ...
# tagcount: number of tags
FNR == 1 {
tag = FILENAME
sub(/\..*$/, "2", tag) # Replace extension with number 2, a.txt ==> a2
if (!(tag in tagfound)) {
tags[tagcount++] = tag
}
tagfound[tag] = 1
}
# For each line in each file, we parse the id, add that id to a list
# then store the value for later display.
# id: abc.def, efg.hij, ...
# idfound: keep track of which id has been found
# ids: List of id, ids[0] = "abc.def", ...
# values: two-dimensional array, values[id,tag] stores the right-
# hand-side of the equal sign
{
sub(/^ */, "") # Remove leading spaces
if (!($1 in idfound)) { ids[idcount++] = $1 }
idfound[$1] = 1
values[$1,tag] = $2
}
# Loop through the ids and tags, display the XML
END {
for (i=0; i<idcount; i++) {
id = ids[i]
printf "<variable id=\"%s\">\n", id
for (j=0; j<tagcount; j++) {
tag = tags[j]
printf " <%s>%s</%s>\n", tag, values[id,tag], tag
}
printf "</variable>\n"
}
}
使用它:
awk -f text2xml.awk a.txt b.txt c.txt # Try out with 3 files
awk -f text2xml.awk *.txt # For all .txt files
我希望我在代码中添加足够的注释以使您理解。如果需要,请随时提出更多问题。
idfound
数组并忘记ids
和idcount
。但是,这种方法并不能保证ID的顺序;而且我觉得秩序很重要。 tagfound
,tagcount
和tags
也是如此。根据phani的要求,我修复了代码以删除标签上的 .txt 。替换以下行:
sub(/\..*$/, "2", tag) # Replace extension with number 2, a.txt ==> a2
使用:
sub(/\.txt$/, "", tag) # Remove the .txt extension
答案 3 :(得分:0)
你快到了。你错放了if块中的空格。它应该是这样的:
if [[ "$A1" = "$B1" && "$A1" = "$C1" ]];then
请注意,开口括号之间没有空格,并且在结束之前有一个空格。
此外,您的测试文件中也存在一些拼写错误。在a.txt
中你应该改变
klm.nop=789
到
kml.nop=789
在c.txt
你应该改变
abca.def=12344
到
abc.def=12344