将3列的文件转换为矩阵

时间:2017-05-15 16:35:18

标签: bash shell matrix awk

我有一个信息分为3列的文件。第一列表示将填充矩阵顶行的类别,第二列表示将在矩阵的第一列中的类别。第三行表示将填充矩阵的大部分的值。原始文件的第1列和第2列可以颠倒,但它没有什么区别。

该文件看起来像这样

Category1   type1   +
Category1   type2   -
Category1   type3   +
Category2   type1   +
Category2   type2   +
Category2   type3   +
Category3   type1   +
Category3   type2   -
Category3   type3   -

我想把它变成一个看起来像这个

的矩阵
    Category1   Category2   Category3
type1   +   +   +
type2   -   +   -
type3   +   +   -

我认为awk可能会这样做,我只是不知道如何让awk这样做

2 个答案:

答案 0 :(得分:1)

private static Context context = null; //new name for android devices private EditText result; FirebaseAuth auth = FirebaseAuth.getInstance(); static SharedPreferences deviceListSharedPreferences; //widgets // Button btnPaired; static ListView devicelist; static ImageView iv; private static DBHandler mdb; private static Set<BluetoothDevice> pairedDevices; String name; static String pass; private String mEmail; String emaill; String mNameRec; String mPassRec; String mMacRec; private static BluetoothAdapter myBluetooth = null; static TextView mName; static TextView mMac; static TextView mNameRecDev; static TextView mMacRecDev; private static ProgressDialog progress; private static String address = ""; private FirebaseAuth mAuth; private FirebaseAuth.AuthStateListener mAuthListener; User userModel = new User(); private static final String TAG ="USER STATUS" ; private OnFragmentInteractionListener mListener; static BluetoothSocket btSocket = null; private static boolean isBtConnected = false; //SPP UUID. Look for it static final UUID myUUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); private String encPass; String decPass; /*Class begins here, other methods omitted due to charectar limit*/ public main() { } @Override public void onViewCreated(View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); iv = (ImageView) view.findViewById(R.id.change); //Calling widgets // // btnPaired = (Button) view.findViewById(R.id.button); devicelist = (ListView) view.findViewById(R.id.listView); mNameRecDev = (TextView)view.findViewById(R.id.nameRec); mMacRecDev = (TextView)view.findViewById(R.id.macRec); try { emaill = mAuth.getCurrentUser().getEmail(); emaill = emaill.replace(".", "<"); System.out.println("Email add:" + emaill); }catch(NullPointerException n){ System.out.println(n.getMessage()); } if (myBluetooth.isEnabled()) { // bluetooth is connected pairedDevicesList(); } iv.setEnabled(false); iv.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // Get the device MAC address, the last 17 chars in the View String device_name = deviceListSharedPreferences.getString(address, mdb.getDeviceName(address)); if (v.getContentDescription().toString().equals("green")) { iv.setImageResource(R.drawable.red); mdb.addLog(new SimpleDateFormat("HH:mm:ss, dd/MM/yyyy").format(new Date().getTime()) + "", MainActivity.name, MainActivity.email, device_name, "0"); iv.setContentDescription("red"); try{ sendCommand("~"+pass); }catch(NullPointerException e){ Toast.makeText(getContext(), "Set password first", Toast.LENGTH_SHORT); }//method to turn on } else { iv.setImageResource(R.drawable.green); mdb.addLog(new SimpleDateFormat("HH:mm:ss, dd/MM/yyyy").format(new Date().getTime()) + "", MainActivity.name, MainActivity.email, device_name, "1"); iv.setContentDescription("green"); try{ sendCommand("`"+pass); }catch(NullPointerException e){ Toast.makeText(getContext(), "Set password first", Toast.LENGTH_SHORT); }//method to turn off } } }); System.out.println(emaill+"HEH"); DatabaseReference mdShare = FirebaseDatabase.getInstance().getReference().child("Shared_With"); mdShare.child(emaill).addValueEventListener(new ValueEventListener() { @Override public void onDataChange(DataSnapshot dataSnapshot) { mNameRec = dataSnapshot.child("Device_Name").getValue().toString(); mMacRec = dataSnapshot.child("Device_MAC").getValue().toString(); mPassRec = dataSnapshot.child("Password").getValue().toString(); decPassrd(mPassRec); mNameRecDev.setText(mNameRec); mMacRecDev.setText(mMacRec); } @Override public void onCancelled(DatabaseError databaseError) { } }); // mNameRecDev.setOnClickListener(this); mMacRecDev.setOnClickListener(this); } private final BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { final String action = intent.getAction(); if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) { final int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR); switch (state) { case BluetoothAdapter.STATE_OFF: Toast.makeText(getActivity(), "Bluetooth needs to be on", Toast.LENGTH_LONG).show(); break; // case BluetoothAdapter.STATE_TURNING_OFF: // do something if needed // break; case BluetoothAdapter.STATE_ON: // pairedDevicesList(); break; // case BluetoothAdapter.STATE_TURNING_ON: // do something if needed // break; } } } }; private static class ConnectBT extends AsyncTask<Void, Void, Void> // UI thread { private boolean ConnectSuccess = true; //if it's here, it's almost connected @Override protected void onPreExecute() { progress = ProgressDialog.show(context, "Connecting...", "Please wait!!!"); //show a progress dialog } // if(iterator.getAddress().equals(DEVICE_ADDRESS)) //Replace with iterator.getName() if comparing Device names. // // { // // device=iterator; //device is an object of type BluetoothDevice // // found=true; // socket = device.createRfcommSocketToServiceRecord(PORT_UUID); socket.connect(); @Override protected Void doInBackground(Void... devices) //while the progress dialog is shown, the connection is done in background { try { if (btSocket == null || !isBtConnected) { myBluetooth = BluetoothAdapter.getDefaultAdapter();//get the mobile bluetooth device BluetoothDevice dispositivo = myBluetooth.getRemoteDevice(address);//connects to the device's address and checks if it's available // btSocket = dispositivo.createInsecureRfcommSocketToServiceRecord(UUID.fromString(dispositivo.getUuids()[0].toString()));//create a RFCOMM (SPP) connection btSocket = dispositivo.createInsecureRfcommSocketToServiceRecord(myUUID);//create a RFCOMM (SPP) connection BluetoothAdapter.getDefaultAdapter().cancelDiscovery(); btSocket.connect();//start connection } } catch (IOException e) { e.printStackTrace(); ConnectSuccess = false;//if the try failed, you can check the exception here } return null; } @Override protected void onPostExecute(Void result) //after the doInBackground, it checks if everything went fine { super.onPostExecute(result); if (!ConnectSuccess) { Toast.makeText(context, "Connection Failed. Are you sure the device is in range and on, or another device is not connected already?", Toast.LENGTH_LONG).show(); } else { //Ahmed: BLUETOOTH IS CONNECTED iv.setEnabled(true); Toast.makeText(context, "Connected.", Toast.LENGTH_SHORT).show(); try{ sendTimedCommand("^"+pass); }catch(NullPointerException e){ Toast.makeText(context, "Set password first", Toast.LENGTH_SHORT); }//tell arduino device is connected // isBtConnected = true; } progress.dismiss(); } } public static ArrayList list = new ArrayList(); public static void pairedDevicesList() { pairedDevices = myBluetooth.getBondedDevices(); list.clear(); if (pairedDevices.size() > 0) { for (BluetoothDevice bt : pairedDevices) { //loop // handling custom names for devices, address => custom name // reading already stored custom names String customName; // Toast.makeText(getActivity(), bt.getAddress() + " => " + bt.getName(), Toast.LENGTH_LONG).show(); //annoying if (mdb.getDeviceName(bt.getAddress()).length() < 2) { customName = deviceListSharedPreferences.getString(bt.getAddress(), bt.getName() + "\n" + bt.getAddress()); } else { customName = deviceListSharedPreferences.getString(bt.getAddress(), mdb.getDeviceName(bt.getAddress())); } list.add(customName); //add the appropriate name to ListView SharedPreferences.Editor editor = listIndexToDeviceAddress.edit(); editor.putString(String.valueOf(list.size() - 1), bt.getAddress()); // puts position => address editor.commit(); } } else { Toast.makeText(context, "No Paired Bluetooth Devices Found.", Toast.LENGTH_LONG).show(); } final ArrayAdapter adapter = new ArrayAdapter(context, android.R.layout.simple_list_item_1, list); devicelist.setAdapter(adapter); devicelist.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View v, int position, long id) { address = listIndexToDeviceAddress.getString(String.valueOf(position), "address not available"); if (address.equals("address not available")){ Toast.makeText(context, "Something went wrong, address not found", Toast.LENGTH_LONG).show(); }else { new ConnectBT().execute(); //Call the class to connect } } }); //Method called when the device from the list is clicked //handling long click devicelist.setOnItemLongClickListener (new AdapterView.OnItemLongClickListener() { public boolean onItemLongClick(AdapterView parent,final View view, final int position, long id) { // TODO Auto-generated method stub android.support.v7.app.AlertDialog.Builder builderSingle = new android.support.v7.app.AlertDialog.Builder(context); // can be used for icon and label: //builderSingle.setIcon(R.drawable.ic_logo); // builderSingle.setTitle("Select One Name:-"); final ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(context, android.R.layout.select_dialog_singlechoice); // hardcoded options arrayAdapter.add("Enter New Name"); arrayAdapter.add("Set Password"); builderSingle.setNegativeButton("cancel", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }); builderSingle.setAdapter(arrayAdapter, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { String strName = arrayAdapter.getItem(which); if (which == 0){ // delete //do your stuff here // get prompts.xml view LayoutInflater li = LayoutInflater.from(context); View promptsView = li.inflate(R.layout.name_prompt, null); AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder( context); // set prompts.xml to alertdialog builder alertDialogBuilder.setView(promptsView); final EditText userInput = (EditText) promptsView .findViewById(R.id.editTextDialogUserInput); // set dialog message alertDialogBuilder .setCancelable(false) .setPositiveButton("OK", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { // get user input and set it to result // edit text Log.d("length", String.valueOf(userInput.getText().toString().length())); if (userInput.getText().toString().length() > 0) { SharedPreferences.Editor editor = deviceListSharedPreferences.edit(); String device_address = listIndexToDeviceAddress.getString(String.valueOf(position), "address not available"); if (!device_address.equals("address not available")) { editor.putString(device_address, userInput.getText().toString()); editor.commit(); pairedDevicesList(); Toast.makeText(context, "Saved", Toast.LENGTH_SHORT).show(); } } else { Toast.makeText(context, "Name empty", Toast.LENGTH_SHORT).show(); } } }) .setNegativeButton("Cancel", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { dialog.cancel(); } }); // create alert dialog AlertDialog alertDialog = alertDialogBuilder.create(); // show it alertDialog.show(); }else if (which == 1){ // share //do your stuff here // get prompts.xml view LayoutInflater li = LayoutInflater.from(context); View promptsView = li.inflate(R.layout.name_prompt, null); AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder( context); // set prompts.xml to alertdialog builder alertDialogBuilder.setView(promptsView); final TextView tv = (TextView) promptsView.findViewById(R.id.name_prompt_label); tv.setText("Enter New Password"); final EditText userInput = (EditText) promptsView .findViewById(R.id.editTextDialogUserInput); // set dialog message alertDialogBuilder .setCancelable(false) .setPositiveButton("OK", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { // get user input and set it to result // set password Log.d("length", String.valueOf(userInput.getText().toString().length())); if (userInput.getText().toString().length() > 0) { // are you sure this is the new password? DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { switch (which){ case DialogInterface.BUTTON_POSITIVE: //Yes button clicked // update or create new password String device_address = listIndexToDeviceAddress.getString(String.valueOf(position), "address not available"); String device_name = deviceListSharedPreferences.getString(device_address, ((String)devicelist.getItemAtPosition(position)).split("\n")[0]); //get saved name otherwise get first line from ListView string if (!device_address.equals("address not available")) { Log.v("address and name", device_address); mdb.updateOrSetNewPassword(device_name, device_address, userInput.getText().toString(), true); Toast.makeText(context, "New Password Set", Toast.LENGTH_SHORT).show(); } dialog.dismiss(); break; case DialogInterface.BUTTON_NEGATIVE: //No button clicked dialog.dismiss(); break; } } }; android.support.v7.app.AlertDialog.Builder builder = new android.support.v7.app.AlertDialog.Builder(context); builder.setMessage("Are you sure you want to change the password to " + userInput.getText().toString() + "?").setPositiveButton("Yes", dialogClickListener) .setNegativeButton("No", dialogClickListener).show(); } else { Toast.makeText(context, "Password field empty empty", Toast.LENGTH_SHORT).show(); } } }) .setNegativeButton("Cancel", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { dialog.cancel(); } }); // create alert dialog AlertDialog alertDialog = alertDialogBuilder.create(); // show it alertDialog.show(); } } }); builderSingle.show(); return true; } }); } } 救援!

awk

答案 1 :(得分:1)

这是一个基于GNU awk的解决方案。我强调这一点,因为多维数组(为方便的解决方案而获得)是特定于GNU awk的特性。

我的脚本table2matrix.awk

# collect values
{
  # category=$1 ; type=$2 ; value=$3
  if (!($1 in categories)) { categories[$1] }
  types[$2][$1] = $3
}
# output of values
END {
  # print col. header
  for (category in categories) { printf("\t%s", category); }
  print ""
  # print rows
  for (type in types) {
    printf("%s", type);
    for (category in categories) {
      printf("\t%s", types[type][category]);
    }
    print ""
  }
}

示例会话:

$ cat >table.txt <<EOF
> Category1   type1   +
> Category1   type2   -
> Category1   type3   +
> Category2   type1   +
> Category2   type2   +
> Category2   type3   +
> Category3   type1   +
> Category3   type2   -
> Category3   type3   -
> EOF

$ awk -f table2matrix.awk table.txt
        Category1       Category2       Category3
type1   +       +       +
type2   -       +       -
type3   +       +       -

$ cat table.txt | sed $'s/   /\t/g' >table-tabs.txt

$ awk -f table2matrix.awk table-tabs.txt 
        Category1       Category2       Category3
type1   +       +       +
type2   -       +       -
type3   +       +       -

$ cat >table-sorted.txt <<EOF
> Category1   type1   +
> Category1   type3   +
> Category2   type1   +
> Category2   type2   +
> Category2   type3   +
> Category3   type1   +
> Category1   type2   -
> Category3   type2   -
> Category3   type3   -
> EOF

$ awk -f table2matrix.awk table-sorted.txt 
        Category1       Category2       Category3
type1   +       +       +
type2   -       +       -
type3   +       +       -

$ tac table.txt >table-reverse.txt

$ awk -f table2matrix.awk table-reverse.txt 
        Category1       Category2       Category3
type1   +       +       +
type2   -       +       -
type3   +       +       -

$ grep '+' table.txt >table-incompl.txt

$ awk -f table2matrix.awk table-incompl.txt 
        Category1       Category2       Category3
type1   +       +       +
type2           +
type3   +       +

$ 

table.txt以空格分隔(从Web浏览器复制/粘贴),table-tabs.txttable.txt,其中的空格序列由制表符替换。

从脚本(但不是Web浏览器中的代码示例)可以看出,输出是以制表符分隔的。

在测试了原始样本输入的一些变体后,我修复了我的awk脚本。它变得有点短,与karafka ...

的其他解决方案更相似