更新的问题 好的,所以我有一个包含这样的行的文件:
44:) 2.884E-02 0.000E+00 0.000E+00 2.780E+02 0.000E+00 0.000E+00 9.990E+02
45:) 2.884E-02 0.000E+00 0.000E+00 2.780E+02 0.000E+00 0.000E+00 9.990E+02
1:) 3.593E-02 0.000E+00 0.000E+00 2.780E+02 0.000E+00 0.000E+00 1.000E+05
2:) 3.593E-02 0.000E+00 0.000E+00 2.780E+02 0.000E+00 0.000E+00 1.000E+05
第一列中的数字从1到x(在本例中为45),然后从1次开始。我想将一些列移动到单独的文件中。我想要移动的列的索引存储在变量/数组$selected_columns
中(在本例中为2,5和8),我想要移动的列数存储在$number_of_columns
中(这种情况3)。
然后我要创建45个文件,一个用于所有1:)
的选定列,一个用于所有2:)
的所选列,依此类推。我想尽可能地使这一点变得通用,因为列数和从1到x的数字都会改变。数字x始终是已知的,要提取的列由用户选择。
原始问题:
我有一个由egrep提取的字符串。然后我想打印该字符串中的一些列(单词)。位置(列索引)在我的bash脚本的列表中是已知的。目前它看起来像这样:
line=$(egrep " ${i}:\)" $1)
for ((j=1; j<=$number_of_columns; j++))
do
awk $line -v current_column=${selected_columns[$j]} '{printf $(current_column)}' > "history_files/history${i}"
done
其中number_of_columns
是要打印的列数,selected_columns
包含这些列的相应索引。作为示例number_of_columns = 3
和selected_columns = [2 5 8]
,我希望将字符串line
中的第2,5和8字打印到文件history${i}
。
我不确定出了什么问题,但这已经做了一些试验和错误。当前错误为awk: cannot open 0.000E+00 (No such file or directory)
。
感谢任何帮助!
答案 0 :(得分:3)
我想,您必须将awk
行更改为:
echo $line | awk -v current_column=${selected_columns[$j]} ...
对于更新的问题,如果列位于数组$selected_columns
中。在示例文件中,列由多个相邻空格分隔。如果您的原始文件不适用,则可以在sed
之前省略grep
。
columns=`echo ${selected_columns[*]} | sed 's/ /,/g'`
for i in `seq 45`; do
sed -e 's/ */ /g' file | grep "^$i:)" | cut -d' ' -f $columns >file-$i
done
答案 1 :(得分:1)
在:
awk $line -v ...
$ line保存grep的输出,可能不是awk期望在它的命令行上看到的东西。还有,这个:
for ((j=1; j<=$number_of_columns; j++))
do
anything > "history_files/history${i}"
done
每次循环时,都会导致您覆盖历史文件。我不知道你到底想要什么。
但是你的脚本还有很多其他问题。你说“作为一个例子,number_of_columns = 3和selected_columns = [2 5 8],所以我想从字符串行打印第2,5和8个字到文件历史记录$ {i}。”。
这完全在awk中是微不足道的,你也不需要在awk之外做一个“grep”,所以你可以完成整个事情:
awk -v pat=" ${i}:\)" -v selected_columns="$selected_columns" '
BEGIN { number_of_columns = split(selected_columns,selected_columnsA) }
$0 ~ pat {
sep=""
for (j=1;j<=number_of_columns;j++) {
current_column = selected_columnsA[j]
printf "%s,%s",sep,lineA[current_column]
sep = "\t"
}
print ""
}
' "$1" > "history_files/history${i}"
如果这对您不起作用,让我们修复它而不是尝试修复原始脚本。听起来你已经把上面的循环包围起来,很可能只是awk脚本的一部分。
基于更新的OP编辑:
我添加了很多评论,但如果您有疑问,请与我联系:
$ cat file
44:) 2.884E-02 0.000E+00 0.000E+00 2.780E+02 0.000E+00 0.000E+00 9.990E+02
45:) 2.884E-02 0.000E+00 0.000E+00 2.780E+02 0.000E+00 0.000E+00 9.990E+02
1:) 3.593E-02 0.000E+00 0.000E+00 2.780E+02 0.000E+00 0.000E+00 1.000E+05
2:) 3.593E-02 0.000E+00 0.000E+00 2.780E+02 0.000E+00 0.000E+00 1.000E+05
$
$ cat tst.sh
selected_columns=(2 5 8)
selCols="${selected_columns[@]}"
awk -v selCols="$selCols" '
BEGIN { # Executed before the first line of the input file is read
# Split the string of selected column numbers, selCols, into
# an array selColsA where selColsA[1] has the value of the
# first space-separated sub-string of selCols (i.e. the number
# of the first column to print). Note that we dont need the
# number of columns passed into the script as a result of
# splitting the string is the count of elements put into the
# array as a return code from the split() builtin function.
numCols = split(selCols,selColsA)
}
{ # Executed once for every line of the input file
# Create a numerix suffix like "45" from the first column
# in the current line of the input file, e.g. "45:)" by
# just getting rid of all non-digit characters.
sfx = $1
gsub(/[^[:digit:]]/,"",sfx)
# Create the name of the output file by attaching that
# numeric suffix to the base value for all output files.
#histfile = "history_files/history" sfx
histfile = "tmp" sfx
# Loop through every column we want printed. selColsA[<index>]
# gives us a column number which we can then use to access the
# columns of the current line. Awk uses the builtin variable $0
# to hold the current line, and it autolatically splits it so
# that $1 holds the first column, $2 is the second, etc. So
# if selColsA[1] has the value 3, then $(selColsA[1]) would be
# the value of the 3rd column of the current input line.
sep=""
for (i=1;i<=numCols;i++) {
curCol = selColsA[i]
# Print the current column, prefixed by a tab for all but
# the first column, and without a terminating newline so the
# next column gets appended to the end of the current output line.
# Note that in awk "> file" has different semantics from shell
# and opens the file for writing the first time the line is hit
# like "> file" in shell, but then appends to it every time its
# hit afterwards, like ">> file" in shell.
printf "%s%s",sep,$curCol > histfile
sep = "\t"
}
# Add a newline to the end of the current output line
print "" > histfile
}
' "$1"
$
$ ./tst.sh file
$
$ cat tmp1
3.593E-02 2.780E+02 1.000E+05
$ cat tmp2
3.593E-02 2.780E+02 1.000E+05
$ cat tmp44
2.884E-02 2.780E+02 9.990E+02
$ cat tmp45
2.884E-02 2.780E+02 9.990E+02
顺便说一句,我上面使用了“专栏”和“专栏”这些词语,因为你刚刚学习,但是你的awk术语实际上是“字段”和“记录”。
答案 2 :(得分:0)
我认为你可以用cut来做你想做的事,即
echo "$line" | cut -d" " -f2 -f5 -f8 > "history_files/history${i}"
-d是你的分隔符,我用空格来测试,因此是“”
希望这会有所帮助