我正在尝试做什么: 我将python文件名传递给我的bash脚本并尝试查找所有方法。我想对它们进行排序并以下列方式显示它们。
function_name file_name:line_number
结果按file_name排序。
简短版本: 我发现使用+ =将元素添加到我的数组时会出现一些意外行为。它看起来像我的第一个文件中的最后一个grep匹配,第二个文件中的第一个grep匹配被粘在一起。有人可以帮我找出原因吗?
长版:
我的代码:
#!/bin/bash/
for i in $*
do
IFS=','
#result+=($(grep -n -o -P '(?<=def).*(?=\()' $i ) )
result+=( $(grep -n -o -P '(?<=def).*(?=\()' $i | sort -t\: -k2 | tr '\n' ',' | sed 's/.$//') )
unset IFS
done
结果如下:
34: div 39: dot 7: drop 24: minus 19: plus 3: push 15: rot 11: swap 29: times 1: one 7: three 4: two
我想:
34: div 39: dot 7: drop 24: minus 1: one 19: plus 3: push 15: rot 11: swap 29: times 7: three 4: two
看了之后,我猜测grep只对传递给它的信息执行排序,而不是对整个结果数组执行排序。这让我相信我需要将grep中的所有结果存储在一个数组中,然后根据文件名对数组进行排序。这是我有各种各样的问题(双关语!)。
我试过了:
#!/bin/bash/
for i in $*
do
IFS=','
result+=($(grep -n -o -P '(?<=def).*(?=\()' $i ) )
#result+=( $(grep -n -o -P '(?<=def).*(?=\()' $i | sort -t\: -k2 | tr '\n' ',' | sed 's/.$//') )
unset IFS
done
#echo ${result[*]}
#for a in "${result[*]}"
#do
# echo $a
#done
IFS=','
cheese=($(sort -t\: -k2 <<< "${result[*]}"))
unset IFS
echo ${cheese[*]}
这更接近,但它看起来像第一个文件中的最后一个grep和第二个文件中的第一个grep卡在一起。 echo回路的输出:
34: div
39: dot 1: one
7: drop
24: minus
19: plus
3: push
15: rot
11: swap
7: three
29: times
4: two
如果点和一个函数粘在一起,我的排序输出是正确的:
34: div 39: dot 1: one 7: drop 24: minus 19: plus 3: push 15: rot 11: swap 7: three 29: times 4: two
输入file1:
def push(n):
global stack
stack = [n] + stack
def drop():
global stack
stack.pop(0)
def swap():
global stack
stack[0], stack[1] = stack[1], stack[0]
def rot():
global stack
stack[0], stack[2] = stack[2], stack[0]
def plus():
global stack
num = stack[0] + stack[1]
stack[:2] = [num]
def minus():
global stack
num = stack[1] - stack[0]
stack[:2] = [num]
def times():
global stack
num = stack[0] * stack[1]
stack[:2] = [num]
def div():
global stack
num = stack[1] / stack[0]
stack[:2] = num
def dot():
global stack
print stack.pop(0)
输入文件2:
def one():
pass
def two():
pass
def three():
pass
---------- ---------- UPDATE
这是我的最终解决方案。以下回复是现货。
#!/bin/bash
declare -a result
for i in "$@"
do
while read line; # Read the input from the grep command for the current file
do
result+=("${line} $i")
done< <( grep -n -o -P '(?<=def).*(?=\()' ${i})
done
#set up for sorting
IFS=$'\n'
#sort the results into sorted by function name
read -r -d '' -a sorted < <(sort -t: -k2 <<<"${result[*]}" && printf '\0')
unset IFS
#for loop for printing
for a in "${sorted[@]}"; do
#set up delimiter
IFS=' '
#split variable a into array printout
read -ra printout <<< "$a"
#get rid of ":" at the end of the number
num=$(echo "${printout[0]}" | cut -d':' -f 1)
#print in format
printf "%s %s:%s\n" "${printout[1]}" "${printout[2]}" "$num"
done
unset IFS
答案 0 :(得分:2)
您的代码存在一些问题。
您不会添加像&#34; 1这样的元素:推送&#34;或&#34; 5:掉落&#34;在数组中,您将grep -n -o -P '(?<=def).*(?=\()' file1
的COMPLETE输出推送到它。下一个输出是grep -n -o -P '(?<=def).*(?=\()' file2
的COMPLETE输出,后面附有逗号。
无需在添加过程中使用IFS。具体来说,在排序过程中这会产生反作用,因为您仍希望在\n
上分开,而不是在\
(空格)上分开。
您应该始终将输入引用到数组中。
你应该声明数组。
如果您的输入可能包含shell globs,则应使用this answer中的信息。
这是工作脚本(您可以用echo ${sorted[*]}
替换最后一行以获得与以前相同的字符串结构。)
#!/bin/bash
declare -a result
for i in "$@"
do
while read line; # Read the input from the grep command for the current file
do
result+=("${line}")
done< <( grep -n -o -P '(?<=def).*(?=\()' ${i})
done
IFS=$'\n'
read -r -d '' -a sorted < <(sort -t: -k2 <<<"${result[*]}" && printf '\0')
unset IFS
printf "[%s]\n" "${sorted[@]}"
纳入@Charles Duffy的建议,谢谢!