我有一个信息分为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这样做
答案 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.txt
为table.txt
,其中的空格序列由制表符替换。
从脚本(但不是Web浏览器中的代码示例)可以看出,输出是以制表符分隔的。
在测试了原始样本输入的一些变体后,我修复了我的awk脚本。它变得有点短,与karafka ...
的其他解决方案更相似