Parsing a list of strings and enumerate them based on line number - regex

Can someone help me take a list of strings and enumerate string values based on line number?
Im trying to figure out how to parse all my known favorite network SSIDs and then assign each SSID a number based on the order from the output. Example:
If I run networksetup -listpreferredwirelessnetworks en0 (on macOS), I get the following output based on my recent Wi-Fi favorites list (Apple calls this the 'Preferred Network' list):
Preferred networks on en0:
Denny's
Hilton Hotel 2465
Hipster Cafe
My_Moms_Basement
Airport_bar
Marriot - Public-5G
OFFICE
I want to parse this output above, search/filter for my corporate SSID ("OFFICE" in this example) and then get its line number (in this case "OFFICE" is listed on line 8 - if you count the header "Preferred networks on en0:").
Ultimately I want to determine if SSID "OFFICE" is at the top of the list or not, and if it's NOT then I'll use the networksetup command to move it to the top - But I only want to take action if SSID "OFFICE" is not already at the top. Apple considers the top line “index 0” in this context (so line/array counting technically starts with 0,1,2,3 etc).
I have tried wc, sort, and various counting loops but I cant seem to get this to give me the output I want.
Thanks!

If you want to assign an index to every line of your file, you could use an array (declare -a in bash)
Assuming the lines you mentioned are in a file named "preferred_networks", you could write this to create the array (one entry of the array for every line) :
declare -a ssid
exec 5<./preferred_networks
((i=0))
while read line<&5; do
ssid[i]=$line
((++i))
done
Then you could read your array (containing $i elements) with the following loop:
for j in `seq 0 $i` ; do
echo ssid[$j]
done

Related

Trace32: Way to set number of rows displayed on a data.dump

For a data.dump, you can set the number of columns of the window displayed with the /columns option, but is there a way to set the number of rows displayed?
If I dump out only 4 addresses, the window is quite large.
If you want to limit the size of any window in TRACE32 use the command WinPOS.
E.g. if you want to have a Data.dump window at address D:0x100 with a hight of only two lines (one for the header and one for the content) use the following two commands:
WinPOS ,,,2.
Data.dump D:0x100
To skip also the header line use:
WinPOS ,,,1,,0
Data.dump D:0x100
You can also size the window like you like with the mouse, and then get the command to open the window exactly like that in you clipboard by using the command ClipSTOre WinTOP
If you want to have a limited dump of addresses use the command Data.dump with an address range as a parameter.
E.g. if you want to see four 32-bit values starting at the address D:0x100 use the command
Data.dump D:0x100--0x10F
or
Data.dump D:0x100++15.
The second from means: Start address and the following number of bytes. (The dot after the 15 in my example indicates that 15 is a decimal number. Without the dot it will probably interpenetrated as a hexadecimal value.)

How to make GDB format half-word memory as hex?

I'm working with an algorithm that uses uint16_t as the datatype. There are 4 half words in the array so I am trying to display the four half words in hex. I have not done anything other than x/4h:
(gdb) x/4h master_key
0x7fffffffd330: u"Āईᄐᤘ桷"
0x7fffffffd33c: u"桷敥\xbe0#"
0x7fffffffd346: u""
0x7fffffffd348: u"ꆋ翿"
According to the GDB | Memory:
f, the display format
The display format is one of the formats used by print (‘x’, ‘d’, ‘u’, ‘o’, ‘t’, ‘a’, ‘c’, ‘f’, ‘s’), and in addition ‘i’ (for machine
instructions). The default is ‘x’ (hexadecimal) initially. The default
changes each time you use either x or print.
I'm not sure why x is trying to print strings but I would like it to print the half words in hex.
GDB does not seem to be following the manual. I think I need to change the behavior of x and make it persistent. How do I tell GDB to print the half words in hex?
The following in in my .gdbinit but it looks like GDB is ignoring it (not a surprise).
(gdb) shell cat ~/.gdbinit
set output-radix 16
set history save on
set history size 256
set logging on
set logging overwrite on

index a text file (lines with different size) in c++

I have to extract information from a text file.
In the text file there is a list of strings.
This is an example of a string: AAA101;2015-01-01 00:00:00;0.784
The value after the last ; is a non integer value, which changes from line to line, so every line has different lenght of characters.
I want to map all of these lines into a structured vector as I can access to a specific line anytime I need without scan the whole file again.
I did some research and I found some threads about a command called, which permit me to reach a specific line of a text file but I read it only works if any line has the same characters lenght of the others.
I was thinking about converting all the lines in the file in a proper format in order to be able to map that file as I want but I hope there is a better and quick way
You can try TStringList*. It creates a list of AnsiStrings. Then each AnsiString can be accessed via ->operator [](numberOfTheLine).

Change WiFi WPA2 passkey from a script

I'm using Raspbian Wheezy, but this is not a Raspberry Pi specific question.
I am developing a C application, which allows the user to change their WiFi Password.
I did not find a ready script/command for this, so I'm trying to use sed.
I pass the SSID name and new key to a bash script, and the key is replaced for the that ssid block within *etc/wpa_supplicant/wpa_supplicant.conf.*.
My application runs as root.
A sample block is shown below.
network={
ssid="MY_SSID"
scan_ssid=1
psk="my_ssid_psk"
}
so far I've tried the following (I've copied the wpa_supplicant.conf to wpa.txt for trying) :
(1) This tries to do the replacement between a range, started when my SSID is detected, and ending when the closing brace, followed by a newline.
SSID="TRIMURTI"
PSK="12345678"
sed -n "1 !H;1 h;$ {x;/ssid=\"${SSID}\"/,/}\n/ s/[[:space:]]*psk=.*\n/\n psk=\"${PSK}\"\n/p;}" wpa.txt
and
(2) This tries to 'remember' the matched pattern, and reproduce it in the output, but with the new key.
SSID="TRIMURTI"
PSK="12345678"
sed -n "1 !H; 1 h;$ {x;s/\(ssid=\"${SSID}\".*psk=\).*\n/\1\"${PSK}\"/p;}" wpa.txt
I have used hold & pattern buffers as the pattern can span multiple lines.
Above, the first example seems to ignore the range & replaces the 1st instance, and then truncates the rest of the file.
The second example replaces the last found psk value & truncates the file thereafter.
So I need help in correcting the above code, or trying a different solution.
If we can assume the fields will always be in a strict order where the ssid= goes before psk=, all you really need is
sed "/^[[:space:]]*ssid=\"$SSID\"[[:space:]]*$/,/}/s/^\([[:space:]]*psk=\"\)[^\"]*/\1$PSK/" wpa.txt
This is fairly brittle, though. If the input is malformed, or if the ssid goes after the psk in your block, it will break. The proper solution (which however is severe overkill in this case) is to have a proper parser for the input format; while that is in theory possible in sed, it would be much simpler if you were to swtich a higher-level language like Python or Perl, or even Awk.
The most useful case is update a password or other value in configuration is to utilize wpa_cli. E.g.:
wpa_cli -i "wlan0" set_network "0" psk "\"Some5Strong1Pass"\"
wpa_cli -i "wlan0" save_config
The save_config method is required to update cfg file: /etc/wpa_supplicant/wpa_supplicant.conf

How to parse text-based table in C++

I am trying to parse a table in the form of a text file using ifstream, and evaluating/manipulating each entry. However, I'm having trouble figuring out how to approach this because of omissions of particular items. Consider the following table:
NEW VER ID NAME
1 2a 4 "ITEM ONE" (2001)
1 7 "2 ITEM" (2002) {OCT}
1.1 10 "SOME ITEM 3" (2003)
1 12 "DIFFERENT ITEM 4" (2004)
1 a4 16 "ITEM5" (2005) {DEC}
As you can see, sometimes the "NEW" column has nothing in it. What I want to do is take note of the ID, the name, the year (in brackets), and note whether there are braces or not afterwards.
When I started doing this, I looked for a "split" function, but I realized that it would be a bit more complicated because of the aforementioned missing items and the titles becoming separated.
The one thing I can think of is reading each line word by word, keeping track of the latest number I saw. Once I hit a quotation mark, make note that the latest number I saw was an ID (if I used something like a split, the array position right before the quotation mark), then keep record of everything until the next quote (the title), then finally, start looking for brackets and braces for the other information. However, this seems really primitive and I'm looking for a better way to do this.
I'm doing this to sharpen my C++ skills and work with larger, existing datasets, so I'd like to use C++ if possible, but if another language (I'm looking at Perl or Python) makes this trivially easy, I could just learn how to interface a different language with C++. What I'm trying to do now is just sifting data anyways which will eventually become objects in C++, so I still have chances to improve my C++ skills.
EDIT: I also realize that this is possible to complete using only regex, but I'd like to try using different methods of file/string manipulation if possible.
If the column offsets are truly fixed (no tabs, just true space chars a la 0x20) I would read it a line at a time (string::getline) and break it down using the fixed offsets into a set of four strings (string::substr).
Then postprocess each 4-tuple of strings as required.
I would not hard-code the offsets, store them in a separate input file that describes the format of the input - like a table description in SQL Server or other DB.
Something like this:
Read the first line, find "ID", and store the index.
Read each data line using std::getline().
Create a substring from a data line, starting at the index you found "ID" in the header line. Use this to initialize a std::istringstream with.
Read the ID using iss >> an_int.
Search the first ". Search the second ". Search the ( and remember its index. Search the ) and remember that index, too. Create a substring from the characters in between those indexes and use it to initialize another std::istringstream with. Read the number from this stream.
Search for the braces.