在带有(财务)帐户的文本文件(accounts.txt)中,子帐户是,并且需要用下划线分隔,如下所示:
assets
assets_hh
assets_hh_reimbursements
assets_hh_reimbursements_ff
......等等。
现在我想从特定的行号中获取特定的子帐户,例如: 第4行的第3栏:
$ lnr=4; fnr=3
$ cut -d $'\n' -f "$lnr" < accounts.txt | cut -d _ -f "$fnr"
reimbursements
$
但fnr = 1和fnr = 2都给出了第一行,它只有一个字段:
$ cut -d $'\n' -f 1 < accounts.txt | cut -d _ -f "fnr"
assets
$
这是不受欢迎的行为。
现在我可以通过在每个帐户前加下划线并为每个必需的字段编号添加1来解决这个问题,但这不是一个优雅的解决方案。 我做错了什么和/或可以通过发出不同的检索命令来改变它吗?
答案 0 :(得分:2)
使用cut -d $'\n' -f "$lnr"
从文件中获取lnr-th
行有点奇怪。更常见的方法是使用sed
,例如:
sed -n "${lnr}p" file | cmd ...
但是,为此,awk
更好 - 在一次调用中也可以处理lnr
和fnr
。
file=accounts.txt
lnr=1
fnr=2
awk -F_ -v l=$lnr -v f=$fnr 'NR==l{print $f}' "$file"
以上所有组合lnr / fnr产生:
line field1 field2 field3 field4
------------------------------------------------------------------------
assets assets
assets_hh assets hh
assets_hh_reimbursements assets hh reimbursements
assets_hh_reimbursements_ff assets hh reimbursements ff
答案 1 :(得分:1)
检查以下解决方案 -
cat f
assets
assets_hh
assets_hh_reimbursements
assets_hh_reimbursements_ff
根据您的评论尝试以下命令 -
$ lnr=1; fnr=2
$ echo $lnr $fnr
1 2
$ awk -v lnr=$lnr -v fnr=$fnr -F'_' 'NR==lnr {print $fnr}' f
###Output is nothing as line 1 column 2 is blank when FS="_"
$ lnr=4;fnr=1
$ echo $lnr $fnr
4 1
$ awk -v lnr=$lnr -v fnr=$fnr -F'_' 'NR==lnr {print $fnr}' f
assets
$ lnr=4;fnr=3
$ echo $lnr $fnr
4 3
$ awk -v lnr=$lnr -v fnr=$fnr -F'_' 'NR==lnr {print $fnr}' f
reimbursements
答案 2 :(得分:0)
一个解决方案是将head|tail
和read
放入数组中,以便更轻松地处理这些项目:
lnr=4
fnr=2
IFS=_ read -r -a arr < <(head -n "$lnr" accounts.txt | tail -n 1)
#note that the array is 0-indexed, so the fieldnumber has to fit that
echo "${arr[$fnr]}"
然后你可以将想法扩展为更有用的功能:
get_field_from_file() {
local fname="$1"
local lnr="$2"
local fnr="$3"
IFS=_ read -r -a arr < <(head -n "$lnr" "$fname" | tail -n 1)
if (( $fnr > ${#arr[@]} )); then
return 1
else
echo "${arr[$fnr]}"
fi
}
field=$(get_field_from_file "accounts.txt" "4" "2") || echo "no such line or field"
[[ -n $field ]] && echo "field: $field"