Bash sort and multi-character tab error - linux

I have data in the following form
C1510438;;C0220832;;2
C0026030;;C0034693;;1
C1257960;;C0007452;;1
C0061461;;C0027922;;2
C0011744;;C0037494;;3
C0014180;;C0034493;;3
When I try to sort on the 3rd field, the command returns the error
sort -t ';;' -k 3 -r -n -o output.txt input.txt
sort: multi-character tab `;;'
I also try with
sort -t $';;' -k 3 -r -n -o output.txt input.txt
but the command returns same error.
Any idea what to do?

The -t option expects a single separator character, but you give it two. A way to do what you want would be to consider that the separator is only a single ;, and thus the third column would become the fifth one:
sort -t ';' -k 5 -r -n -o output.txt input.txt

Since the -t option expects a single separator character, a good way to handle this would be to use a replace tool to temporarily replace the separator(s) with a new one, do the sort, and then restore the original separator(s) as needed for further processing. I have a file that uses "," as separator which I can temporarily replace with a | (pipe), do my sort, and then restore "," as separator.

Related

How can I insert commas in 1 word that I have tailed

I have a log tailed with the following output:
$ tail -n1 /home/shares/number-10.log
123456
I want the output to be: 12,34,56
tail -n1 /home/shares/number-10.log | sed -r 's/([[:digit:]]{2})/\1,/g;s/,[[:space:]]?+$//'
Enable sed regular expression interpretation with -r or -E and then substitute all cases of a digit occurring two times with the two digits followed by a comma. Then in the second statement, remove the comma at the end.
Amended answer as requested:
tail -n1 /home/shares/number-10.log | sed -r 's/([[:digit:]]{2})/\1|/g;s/|[[:space:]]?+$//'
Does the same as the first example but uses "|" instead of ","
It is also possible to use the bash variable operations:
var=`tail -n1 /home/shares/number-10.log`
echo "${var:0:2},${var:2:2},${var:4:2}"
echo "${var:0:2}|${var:2:2}|${var:4:2}"

similarity between the two files using grep, why this work: grep -i "-ffile1" file2

I have two files, file1 and file2, and want to find the similarity between the two files using grep.
why -f should flow by the file name without spaces when I surround the -f file1 with quotes?
this will work
grep -i "-ffile1" file2
but this will not work
grep -i "-f file1" file2
but if I remove the quotes these two cases will work
grep -i -ffile1 file2
grep -i -f file1 file2
By convention, one-letter options with arguments can be either presented as two arguments, i.e. either
(1)
Nth parameter to grep : -f
(N+1)st parameter to grep : the filename.
or
(2)
as a single parameter, where the name immedately follows the option letter: -ffilename
In your second attempt, "-f xxxx", you are passing a single parameter (which corresponds to case (2)), but what follows immediately after the option letter, is a space. Hence you specify a file name starting with a space. Such a file does not exist. Therefore, you see a different behaviour in this case.
The -f option can be used in two ways: either by specifying the file name in the next argument, or by specifying the file name in the same argument right after -f.
When you quote the argument like "-f file1", the second case kicks in and grep looks for a file called " file1", with a leading space. Since your file is called "file1", without a leading space, grep fails to find it.
If the file did have a leading space in its name, it would work:
$ echo findthis > " file1"
$ echo findthis > file2
$ grep -nH "-f file1" file2
file2:1:findthis

Sort numbers values - separated by a dot or any other separator character - Sort versions values in RHEL5

Linux RHEL5 machine
How can I sort the following input to get 1.0.0.1019 in latest variable? Tried -t, -k and -n but it didn't help or may be I'm missing something.
$ echo '1.0.0
1.0.0.1018
1.0.0.1019
1.0.0.1019
1.0.0.7' | sort -u
Could you please try following and let me know if this helps(tested with GNU sort):
echo "1.0.0
1.0.0.1018
1.0.0.1019
1.0.0.1019
1.0.0.7" | sort --version-sort --field-separator=. --key=4 -r
Above will give 1019 in first place(latest one) in case you want it to last place then remove -r in above code please.
sort -n -t. -k1,4
Sort the input numerically.
Fields are separated by '.'
Only use the first four fields, in that order.

Cut and Awk command : Delimiter behaviour

I tried to use cut command to get a list of file names and their sizes from "ls -l" command output.
$ ls -l | cut -f 5,9 -d " "
It gives me output based on 'SINGLE WHITE SPACE' as a delimiter. When "ls -l" output contains consecutive spaces in certain rows, then the output of the command is not proper for those rows.
The rows which have only single white space as column separator, give correct output.
When I run following command:
$ ls -l | awk '{ print $5"\t"$9 }'
awk is ignoring multiple spaces and properly extracting columns from "ls -l" output.
While, cut is treating each space as a delimiter, there by putting values in wrong columns.
It gives correct output for all rows.
Why is this happening ? What can I do to work this out with cut command ?
awk splits fields on whitespace. cut splits fields on a delimiting character. awk is the better tool for this problem.
As an alternative, you can pipe ls -l into a utility that either compresses multiple space chars (maybe tr -s), or into a utility that replaces multiple space chars with a single one (maybe sed). Then cut will do what you want it to.
Don't parse ls -- your code will not print the full filename if it contains spaces. To get the file size and name, use stat:
stat -c "%s %n" *
try this?:
ls -l | tr -s ' ' | cut -d ' ' -f 5, 9

Find line number in a text file - without opening the file

In a very large file I need to find the position (line number) of a string, then extract the 2 lines above and below that string.
To do this right now - I launch vi, find the string, note it's line number, exit vi, then use sed to extract the lines surrounding that string.
Is there a way to streamline this process... ideally without having to run vi at all.
Maybe using grep like this:
grep -n -2 your_searched_for_string your_large_text_file
Will give you almost what you expect
-n : tells grep to print the line number
-2 : print 2 additional lines (and the wanted string, of course)
You can do
grep -C 2 yourSearch yourFile
To send it in a file, do
grep -C 2 yourSearch yourFile > result.txt
Use grep -n string file to find the line number without opening the file.
you can use cat -n to display the line numbers and then use awk to get the line number after a grep in order to extract line number:
cat -n FILE | grep WORD | awk '{print $1;}'
although grep already does what you mention if you give -C 2 (above/below 2 lines):
grep -C 2 WORD FILE
You can do it with grep -A and -B options, like this:
grep -B 2 -A 2 "searchstring" | sed 3d
grep will find the line and show two lines of context before and after, later remove the third one with sed.
If you want to automate this, simple you can do a Shell Script. You may try the following:
#!/bin/bash
VAL="your_search_keyword"
NUM1=`grep -n "$VAL" file.txt | cut -f1 -d ':'`
echo $NUM1 #show the line number of the matched keyword
MYNUMUP=$["NUM1"-1] #get above keyword
MYNUMDOWN=$["NUM1"+1] #get below keyword
sed -n "$MYNUMUP"p file.txt #display above keyword
sed -n "$MYNUMDOWN"p file.txt #display below keyword
The plus point of the script is you can change the keyword in VAL variable as you like and execute to get the needed output.

Resources