sed to insert characters in a specific column - sed

Can anyone tell me how to insert chr to every character in the first column.
file in
1 34566 34765
2 45678 45789
3 34567 34799
X 67895 66900
Y 34567 34890
file out
chr1 34566 34765
chr2 45678 45789
chr3 34567 34799
chrX 67895 66900
chrY 34567 34890
I can't figure out how to make sed -i apply to a specific column. I'm not good with the syntax so if you could break down your explanation I would be grateful. Also, would it be better to use awk for this?

With sed:
sed 's/^/chr/' file.in > file.out
You don't need the -i-flag because you aren't overwriting the input-file file.in.
With awk:
awk '{print "chr"$0}' file.in > file.out

sed 's|^|chr|' file_in > file_out
This does a substitution (s) at the beginning of each line (^) and replacing it with the characters "chr". The pipes (|) are just separators.

With awk:
awk '{print "chr"$0}' file
To store the changes back to the file:
awk '{print "chr"$0}' file > tmp && mv tmp file

$ cat file.in
1 34566 34765
2 45678 45789
3 34567 34799
X 67895 66900
Y 34567 34890
$ awk '$1="chr"$1 {print}' file.in
chr1 34566 34765
chr2 45678 45789
chr3 34567 34799
chrX 67895 66900
chrY 34567 34890
In essence, you are redirecting value of "chr"$1 back to $1 regardless if there are spaces before column 1 or not and still print out the rest of the line.

sed 's/^\s*/chr/'
just to be sur that no white space are before you object. If you are sur of, no need of th \s

awk '{print "chr"$0}'
Works for the file in question because there are no field separators. For that case you can use (for a pipe delimited file for instance):
awk 'BEGIN { FS = "|";OFS="|"} {$97="chr"$0;print}'

Related

xargs and sed to extract specific lines

I want to extract lines that have a particular pattern, in a certain column. For example, in my 'input.txt' file, I have many columns. I want to search the 25th column for 'foobar', and extract only those lines that have 'foobar' in the 25th column. I cannot do:
grep foobar input.txt
because other columns may also have 'foobar', and I don't want those lines. Also:
the 25th column will have 'foobar' as part of a string (i.e. it could be 'foobar ; muller' or 'max ; foobar ; john', or 'tom ; foobar35')
I would NOT want 'tom ; foobar35'
The word in column 25 must be an exact match for 'foobar' (and ; so using awk $25=='foobar' is not an option.
In other words, if column 25 had the following lines:
foobar ; muller
max ; foobar ; john
tom ; foobar35
I would want only lines 1 & 2.
How do I use xargs and sed to extract these lines? I am stuck at:
cut -f25 input.txt | grep -nw foobar | xargs -I linenumbers sed ???
thanks!
Do not use xargs and sed, use the other tool common on so many machines and do this:
awk '{if($25=="foobar"){print NR" "$0}}' input.txt
print NR prints the line number of the current match so the first column of the output will be the line number.
print $0 prints the current line. Change it to print $25 if you only want the matching column. If you only want the output, use this:
awk '{if($25=="foobar"){print $0}}' input.txt
EDIT1 to match extended question:
Use what #shellter and #Jotne suggested but add string delimiters.
awk -vFPAT="([^ ]*)|('[^']*')" -vOFS=' ' '$25~/foobar/' input.txt
[^ ]* matches all characters that are not a space.
'[^']*' matches everything inside single quotes.
EDIT2 to exclude everything but foobar:
awk -vFPAT="([^ ]*)|('[^']*')" -vOFS=' ' "\$25~/[;' ]foobar[;' ]/" input.txt
[;' ] only allows ;, ' and in front and after foobar.
Tested with this file:
1 "1 ; 1" 4
2 'kom foobar' 33
3 "ll;3" 3
4 '1; foobar' asd
7 '5 ;foobar' 2
7 '5;foobar' 0
2 'kom foobar35' 33
2 'kom ; foobar' 33
2 'foobar ; john' 33
2 'foobar;paul' 33
2 'foobar1;paul' 33
2 'foobarli;paul' 33
2 'afoobar;paul' 33
and this command awk -vFPAT="([^ ]*)|('[^']*')" -vOFS=' ' "\$2~/[;' ]foobar[;' ]/" input.txt
To get the line with foobar as part of the 25 field.
awk '$25=="foobar"' input.txt
$25 25th filed
== equal to
"foobar"
Since no action spesified, print the complete line will be done, same as {print $0}
Or
awk '$25~/^foobar$/' input.txt
This might work for you (GNU sed):
sed -En 's/\S+/\n&\n/25;s/\n(.*foobar.*)\n/\1/p' file
Surround the 25th field by newlines and pattern match for foobar between newlines.
If you only want to match the word foobar use:
sed -En 's/\S+/\n&\n/25;s/\n(.*\<foobar\>.*)\n/\1/p' file

I need to remove only the third space in my perl code

I have a file with multiple spaces and i am replacing the spaces with only a single space using :
system "sed -i -e 's/[[:space:]]\\+/ /g' /home/donovan/Documents/NWPMIK.txt";
How can i now go and remove any spaces after the third space?
You can use perl's auto-splitting feature for this:
perl -lane 'push #F, join("", splice(#F,3)); print join " ", #F'
Example:
% echo 'abc def ghi jkl mno pqr' | perl -lane 'push #F, join("", splice(#F,3)); print join " ", #F'
abc def ghi jklmnopqr
This perl on-liner will remove any space after the 3rd space. What it actually does is replace every sequence of at least 3 spaces with just 3 spaces and write the results to a new file :
perl -pe 's/\s{3,}/ /g' /home/donovan/Documents/NWPMIK.txt > /home/donovan/Documents/NWPMIK_new.txt
If you are looking to update the file in-place, then :
perl -pi -e 's/\s{3,}/ /g' /home/donovan/Documents/NWPMIK.txt

divide each line in equal part

I would be happy if anyone can suggest me command (sed or AWK one line command) to divide each line of file in equal number of part. For example divide each line in 4 part.
Input:
ATGCATHLMNPHLNTPLML
Output:
ATGCA THLMN PHLNT PLML
This should work using GNU sed:
sed -r 's/(.{4})/\1 /g'
-r is needed to use extended regular expressions
.{4} captures every four characters
\1 refers to the captured group which is surrounded by the parenthesis ( ) and adds a space behind this group
g makes sure that the replacement is done as many times as possible on each line
A test; this is the input and output in my terminal:
$ echo "ATGCATHLMNPHLNTPLML" | sed -r 's/(.{4})/\1 /g'
ATGC ATHL MNPH LNTP LML
I suspect awk is not the best tool for this, but:
gawk --posix '{ l = sprintf( "%d", 1 + (length()-1)/4);
gsub( ".{"l"}", "& " ) } 1' input-file
If you have a posix compliant awk you can omit the --posix, but --posix is necessary for gnu awk and since that seems to be the most commonly used implementation I've given the solution in terms of gawk.
This might work for you (GNU sed):
sed 'h;s/./X/g;s/^\(.*\)\1\1\1/\1 \1 \1 \1/;G;s/\n/&&/;:a;/^\n/bb;/^ /s/ \(.*\n.*\)\n\(.\)/\1 \n\2/;ta;s/^.\(.*\n.*\)\n\(.\)/\1\2\n/;ta;:b;s/\n//g' file
Explanation:
h copy the pattern space (PS) to the hold space (HS)
s/./X/g replace every character in the HS with the same non-space character (in this case X)
s/^\(.*\)\1\1\1/\1 \1 \1 \1/ split the line into 4 parts (space separated)
G append a newline followed by the contents of the HS to the PS
s/\n/&&/ double the newline (to be later used as markers)
:a introduce a loop namespace
/^\n/bb if we reach a newline we are done and branch to the b namespace
/^ /s/ \(.*\n.*\)\n\(.\)/\1 \n\2/;ta; if the first character is a space add a space to the real line at this point and repeat
s/^.\(.*\n.*\)\n\(.\)/\1\2\n/;ta any other character just bump along and repeat
:b;s/\n//g all done just remove the markers and print out the result
This work for any length of line, however is the line is not exactly divisible by 4 the last portion will contain the remainder as well.
perl
perl might be a better choice here:
export cols=4
perl -ne 'chomp; $fw = 1 + int length()/$ENV{cols}; while(/(.{1,$fw})/gm) { print $1 . " " } print "\n"'
This re-calculates field-width for every line.
coreutils
A GNU coreutils alternative, field-width is chosen based on the first line of infile:
cols=4
len=$(( $(head -n1 infile | wc -c) - 1 ))
fw=$(echo "scale=0; 1 + $len / 4" | bc)
cut_arg=$(paste -d- <(seq 1 $fw 19) <(seq $fw $fw $len) | head -c-1 | tr '\n' ',')
Value of cut_arg is in the above case:
1-5,6-10,11-15,16-
Now cut the line into appropriate chunks:
cut --output-delimiter=' ' -c $cut_arg infile

Brocade alishow merge two consecutive lines awk sed

How would like to join two lines usung awk or sed?
For example, I have data like below:
abcd
12:12:12:12:12:12:12:12
efgh001_01
45:45:45:45:45:45:45:45
ijkl7464746
78:78:78:78:78:78:78:78
and I need output like below:
abcd 12:12:12:12:12:12:12:12
efgh001_01 45:45:45:45:45:45:45:45
ijkl7464746 78:78:78:78:78:78:78:78
Running this almost works, but I need the space or tab:
awk '!(NR%2){print$0p}{p=$0}'
You're almost there:
awk '(NR % 2 == 0) {print p, $0} {p = $0}'
With sed you can do that as follows:
sed -n 'N;s/\n/ /p' file
where:
N reads next line
s replaces the new line character with a space to join both lines properly
p prints the result
This might work for you:
sed '$!N;s/\n/ /' file
or this:
paste -sd' \n' file

remove string between two character with sed

I have a file of this type:
16:00 [61]Al-Najma - Al-Rifaa [62]5.06 [63]3.55 [64]1.57 4
and i want remove all the strings inside square parentheses in order to obtain
16:00 Al-Najma - Al-Rifaa 5.06 3.55 1.57 4
I am trying with sed in this manner:
sed 's/\[.*]//g' file1 > file2
but i obtain
16:00 1.57 4
and with
sed 's/\[.[1234567890]]//g' file1 > file2
does not work if the string contains more than 2 digit.
how can i do this?
your pattern allows only one character, adding a star behind the pattern widens it to all matching characters.
sed 's/\[.[1234567890]]*//g' file1 > file2
alternative:
sed 's/\[^\]*//g' file1 > file2
that means: after the starting "[" everything but the "]" is OK, and that for as many characters as there come (the "*")
for further reading on sed: http://www.grymoire.com/Unix/Sed.html
Your first regex does not work because the quantifier * is greedy, meaning it matches as many characters as possible. Since . also matches brackets, it continues to match until the last closing bracket ] it can find.
So you basically have two options: Use a non-greedy quantifier or restrict the types of characters you can match. You have tried the second solution. I would go with using a negated character class instead:
sed 's/\[[^]]*\]//g'
I'm not sure if sed has non-greedy quantifiers, but perl does:
perl -lpwe 's/\[.*?\]//g'
Does escaping the closing ] help ?
sed 's/\[.*\]//g' file1 > file2
You already got the sed answer, so I will add other one using awk:
awk '
BEGIN {
FS = "\\[[^]]*\\]";
OFS = " "
}
{
for (i=1; i<=NF; i++)
printf "%s", $i
}
END {
printf "\n"
}
' <<<"16:00 [61]Al-Najma - Al-Rifaa [62]5.06 [63]3.55 [64]1.57 4"
Output:
16:00 Al-Najma - Al-Rifaa 5.06 3.55 1.57 4
using awk:
$ echo '16:00 [61]Al-Najma - Al-Rifaa [62]5.06 [63]3.55 [64]1.57 4' | awk -F '\[[0-9]*\]' '$1=$1'
16:00 Al-Najma - Al-Rifaa 5.06 3.55 1.57 4
This might work for you:
echo "16:00 [61]Al-Najma - Al-Rifaa [62]5.06 [63]3.55 [64]1.57 4" |
sed 's/\[[^]]*\]//g'
16:00 Al-Najma - Al-Rifaa 5.06 3.55 1.57 4