我有一个制表符分隔文件,如下所示:
cat my file.txt
给出:
1 299
1 150
1 50
1 57
2 -45
2 62
3 515
3 215
3 -315
3 -35
3 3
3 6789
3 34
5 66
5 1334
5 123
我想使用Unix命令获取基于制造商分隔的文件,该文件基于第1列中的值,输出文件的每一列都将包含第2列的所有相关值 (我在这里使用的是分隔符“|”而不是tab,仅用于说明我想要的输出文件):
299 | -45 | 515 | 66
150 | 62 | 215 | 1334
50 | | -315 |
57 | | -35 |
| | 3 |
相应的Headers(1,2,3,5;基于第1列值)可能是代码的一个很好的补充(如下所示),但主要的要求是将第一个文件的信息拆分成分隔列。谢谢!
1 | 2 | 3 | 5
299 | -45 | 515 | 66
150 | 62 | 215 | 1334
50 | | -315 |
57 | | -35 |
| | 3 |
答案 0 :(得分:2)
这是一个与您的输出相匹配的衬垫。它构建一个字符串$ARGS
,其中包含与第一列中的唯一值一样多的进程替换。然后,$ARGS
用作paste
命令的参数:
HEADERS=$(cut -f 1 file.txt | sort -n | uniq); ARGS=""; for h in $HEADERS; do ARGS+=" <(grep ^"$h"$'\t' file.txt | cut -f 2)"; done; echo $HEADERS | tr ' ' '|'; eval "paste -d '|' $ARGS"
输出:
1|2|3|5
299|-45|515|66
150|62|215|1334
50||-315|
57||-35|
||3|
答案 1 :(得分:1)
您可以使用gnu-awk
awk '
BEGIN{max=0;}
{
d[$1][length(d[$1])+1] = $2;
if(length(d[$1])>max)
max = length(d[$1]);
}
END{
PROCINFO["sorted_in"] = "@ind_num_asc";
line = "";
flag = 0;
for(j in d){
line = line (flag?"\t|\t":"") j;
flag = 1;
}
print line;
for(i=1; i<=max; ++i){
line = "";
flag = 0;
for(j in d){
line = line (flag?"\t|\t":"") d[j][i];
flag = 1;
}
print line;
}
}' file.txt
你得到了
1 | 2 | 3 | 5 299 | -45 | 515 | 66 150 | 62 | 215 | 1334 50 | | -315 | 57 | | -35 | | | 3 |
或者,您可以使用python
....例如split2Columns.py
import sys
records = [line.split() for line in open(sys.argv[1])]
import collections
records_dict = collections.defaultdict(list)
for key, val in records:
records_dict[key].append(val)
from itertools import izip_longest
print "\t|\t".join(records_dict.keys())
print "\n".join(("\t|\t".join(map(str,l)) for l in izip_longest(*records_dict.values(), fillvalue="")))
python split2Columns.py file.txt
你得到相同的结果
答案 2 :(得分:1)
@Jose Ricardo Bustos M. - 谢谢你的回答!我很遗憾无法在我的Mac上安装gnu-awk,但基于你的暗示性答案,我使用awk执行了类似的操作:
private final static String SELECTED_ITEM = "MyAdapter.mSelectedItem";
//Save your selection
@Override
public void onSaveInstanceState(Bundle outState) {
if(null!=mAdapter){
outState.putInt(SELECTED_ITEM, mAdapter.mSelectedItem);
}
super.onSaveInstanceState(outState);
}
//Restore your selection
@Override
public void onActivityCreated(Bundle savedInstanceState){
super.onActivityCreated(savedInstanceState);
if (savedInstanceState != null) {
mAdapter.notifyItemChanged(platformsAdapter.mSelectedItem);
mAdapter.mSelectedItem = savedInstanceState.getInt(SELECTED_ITEM, 0);
mAdapter.notifyItemChanged(platformsAdapter.mSelectedItem);
mRecyclerView.post(new Runnable() {
@Override
public void run() {
//Align selection to top
mLayoutManager
.scrollToPositionWithOffset(mAdapter.mSelectedItem, 0);
}
});
}
}
答案 3 :(得分:0)
这是使用数组来跟踪列标题,使用它们来命名临时文件和paste
最终所有内容:
#!/bin/bash
infile=$1
filenames=()
idx=0
while read -r key value; do
if [[ "${filenames[$idx]}" != "$key" ]]; then
(( ++idx ))
filenames[$idx]="$key"
echo -e "$key\n----" > "$key"
fi
echo "$value" >> "$key"
done < "$1"
paste "${filenames[@]}"
rm "${filenames[@]}"