I am trying to use this command to remove all < and > and + characters from a string. But the command tr is inserting a space character in its place. I want to also remove all spaces.
In
<ModelName>.<123456798123465>.
Out
ModelName . 123456798123465 .
Expected Output
ModelName.123456798123465.
Command used
String | tr '<>+,' ' '
What am I missing here ?
If you want to delete specific characters, use tr -d SET. tr SET ' ' means to translate all characters in SET to space characters.
$ echo '<ModelName>.<123456798123465>.' | tr '<>+' ' '
ModelName . 123456798123465 .
$ echo '<ModelName>.<123456798123465>.' | tr -d '<>+'
ModelName.123456798123465.
You could use sed instead of tr like below.
$ echo '<ModelName>.<123456798123465>.' | sed 's/[+<>]//g'
ModelName.123456798123465.
Character class [+<>] matches all the + or < or > symbols. By replacing the matched characters with an empty string will give the desired output.
What you need is the -d option of tr command
$ echo "<ModelName>.<123456798123465>." | tr -d '<>+,'
ModelName.123456798123465.
From the man pages
-d, --delete
delete characters in SET1, do not translate
Related
I have 9 different files, I'm looping over each, and taking the first, second and third line.
This is my code:
if [ -f displayStudentsInfo.txt ];
then
rm displayStudentsInfo.txt
fi
for f in 20*.txt
do
sed -n '1p' "$f" | cut -d' ' -f3 > anyfile.txt
sed -n '2p' "$f" | cut -d' ' -f2 >> anyfile.txt
sed -n '3p' "$f" | cut -d' ' -f2- >> anyfile.txt
sed -E '$!s/\r?$/, /' anyfile.txt | tr -d \\r\\n >> displayStudentsInfo.txt
done
cat displayStudentsInfo.txt
rm anyfile.txt
I have used this command to add each file on a line, but unfortunately, all the files are being added on the same line.
sed -E '$!s/\r?$/, /' anyfile.txt | tr -d \\r\\n
Output:
201664003, 2.8, Mathematics201700128, 3.2, Pharmacy201703451, 2.2, Political Science201759284, 3.4, Marketing201800082, 3.3, Information Technology Management201800461, 2.7, Information Technology Management201800571, 2.7, Information Technology Management201804959, 3.4, Computer Science201806050, 3.5, Computer Science201806715, 3, Computer Science201942365, 3.6, Computer Science
One idea using awk and printf (sans a '\n' so all output is appended to single line):
awk '
{ printf "%s%s", pfx, $0 # print prefix and current line; prefix initially = ""
pfx=", " # set prefix to ", " for subsequent lines
}
END { printf "\m" } # add a linefeed at the end
' display.txt
This generates:
201664003, GPA: 3.6, Major: Computer Science
NOTE: This may not work if, as indicated in other comments, there are some undesirable non-printing characters in the input file.
Seems like you have Windows line endings (CR LF) instead of Linux line endings (just LF).
The whole file is still printed, but because of the CR the console overwrites already printed letters. You can confirm this by looking at the hexdump tr '\n' ', ' < display.txt | hexdump -c.
To fix this, remove the CRs. Also, tr can only replace single letters. To replace a single letter \n with two letters , insert those two letters using sed.
With sed you can also make sure, that , is only inserted between the lines, but not at the end.
sed -E '$!s/\r?$/, /' display.txt | tr -d \\r\\n; echo
The tr also deletes the \n at the end of the file. This breaks the convention that every output/file should end with a linebreak. Therefore, we add that linebreak again by executing echo afterwards.
sed command explained:
$! for every line except the last one
s/.../.../ replace
\r? an optional CR
and the empty string before the end of the line (\n)
with ,
I would like print strings/texts after every ! (exclamation mark) in bash.
Example string/text:
check_queue!TEST_IN!Queue!400!750
I want this output:
TEST_IN Queue 400 750
I have tried this:
cat filename | cut -d "!" -f2
You were almost there:
cut -d! -f2- filename | tr '!' ' '
-f2- means field 2 and all following fields
No need for cat, just work on file
tr '!' ' ' translates exclamation mark ! to space .
Or if your version of cut has an --output-delimiter= option:
cut --delimiter=! --fields=2- --output-delimiter=' ' filename
Or using awk:
awk -F! '{$1=""; print substr($0,2)}' filename
-F!: Sets the field delimiter to !
$1="": Erase first field
print substr($0,2): Print the whole record starting at 2nd character, since first one is blank delimiter remain from erased first field.
Fist apply a FOREACH line loop
while read s; do
#foreach substring
for (( i=0; i<${#s}; i++ )); do
if ["${s:$i:1}" != “!”] then
#add to the String the extra letter
String="${s} ${s:$i:1}"
else
#print each time you find !
print String
#prepare it to print next String
String =“”
fi
done
done <your filename.txt
my text-
(
"en-US"
)
what i need -
en-US
currently im able to get it by piping it with
... | tr -d '[:space:]' | sed s/'("'// | sed s/'("'// | sed s/'")'//
I wonder if there is a simple way to extract the string between the qoutes rather than chopping off useless parts one by one
... | grep -oP '(?<=").*(?=")'
Explanation:
-o: Only output matching string
-P: Use Perl style RegEx
(?<="): Lookbehind, so only match text that is preceded by a double quote
.*: Match any characters
(?="): Lookahead, so only match text that is followed by a double quote
With sed
echo '(
"en-US"
)' | sed -rn 's/.*"(.*)".*/\1/p'
with 2 commands
echo '(
"en-US"
)' | tr -d "\n" | cut -d '"' -f2
Could you please try following. Where var is the bash variable haveing shown sample value stored in it.
echo "$var" | awk 'match($0,/".*"/){print substr($0,RSTART+1,RLENGTH-2)}'
Explanation: Following is only for explanation purposes.
echo "$var" | ##Using echo to print variable named var and using |(pipe) to send its output to awk command as an Input.
awk ' ##Starting awk program from here.
match($0,/".*"/){ ##using match function of awk to match a regex which is to match from till next occurrence of " by this match 2 default variables named RSTART and RLENGTH will be set as per values.
print substr($0,RSTART+1,RLENGTH-2) ##Where RSTART means starting point index of matched regex and RLENGTH means matched regex length, here printing sub-string whose starting point is RSTART and ending point of RLENGTH to get only values between " as per request.
}' ##Closing awk command here.
Consider using
... | grep -o '"[^"]\{1,\}"' | sed -e 's/^"//' -e 's/"$//'
grep will extract all substrings between quotes (excluding empty ones), the sed later will remove the quotes on both ends.
And this one ?
... | grep '"' | cut -d '"' -f 2
It works if you have just 1 quoted value by line.
I am trying to replace a pipe character in an String with the escaped character in it:
Input: "text|jdbc"
Output: "text\|jdbc"
I tried different things with tr:
echo "text|jdbc" | tr "|" "\\|"
...
But none of them worked.
Any help would be appreciated.
Thank you,
tr is good for one-to-one mapping of characters (read "translate").
\| is two characters, you cannot use tr for this. You can use sed:
echo 'text|jdbc' | sed -e 's/|/\\|/'
This example replaces one |. If you want to replace multiple, add the g flag:
echo 'text|jdbc' | sed -e 's/|/\\|/g'
An interesting tip by #JuanTomas is to use a different separator character for better readability, for example:
echo 'text|jdbc' | sed -e 's_|_\\|_g'
You can take advantage of the fact that | is a special character in bash, which means the %q modifier used by printf will escape it for you:
$ printf '%q\n' "text|jdbc"
text\|jdbc
A more general solution that doesn't require | to be treated specially is
$ f="text|jdbc"
$ echo "${f//|/\\|}"
text\|jdbc
${f//foo/bar} expands f and replaces every occurance of foo with bar. The operator here is /; when followed by another /, it replaces all occurrences of the search pattern instead of just the first one. For example:
$ f="text|jdbc|two"
$ echo "${f/|/\\|}"
text\|jdbc|two
$ echo "${f//|/\\|}"
text\|jdbc\|two
You can try with awk:
echo "text|jdbc" | awk -F'|' '$1=$1' OFS="\\\|"
Creating a printout file from a mysql query, I insert a separation line after every TOTAL string with:
sed -i /^TOTAL/i'-------------------------------------------------- ' file.txt
Is there any more elegante way to repeat n "-" characters instead of typing them?
For instance, if I had to simply generate a line without finding/inserting, I would use:
echo -$-{1..50} | tr -d ' '
but don't know how to do something similar with sed into a file.
Thanks!
Just combine the two:
sed -i /^TOTAL/i"$(echo -$___{1..50} | tr -d ' ')" file.txt
With perl, you can repeat a character N times, see :
perl -pe 's/^TOTAL.*/"-"x50 . "\n$&"/e' file.txt
or :
perl -pe 's/^TOTAL.*/sprintf("%s\n%s", "-"x50, $&)/e' file.txt
and you keep a syntax close to sed.
Another way using builtin printf and bash brace expansion :
sed -i "/^TOTAL/i $(printf '%.0s-' {0..50})" file.txt