How to replace particular string in table column value in PostgreSQL - postgresql

I am trying to replace certain text with other text in PostgreSQL.
To be more specific, I am trying to replace image path and anchor href in article (table blog_posts) from relative to absolute path. Some of the images and anchors already have an absolute path that should not get disturbed.
I tried to select the records which I need to modify:
SELECT
bp.id,
bp.article,
FROM
blog_posts bp
WHERE
bp.article LIKE '%src=%"/fixed_word/%'
OR
bp.article LIKE '%src="/fixed_word/%'
OR
bp.article LIKE '%href="/fixed_word/%'
OR
bp.article LIKE '%href=%"/fixed_word/%'
now I am not sure how to proceed further to update. Please help to get right solution.
My data is something like this:
MyTable: blog_posts
id article
1 any text <img any-atribute src="/fixed_word/variable_word1/something.png"/> any text
2 any text <a any-attribute href="/fixed_word/variable_word2/something2.png"><img src="/fixed_word/variable_word2/something2.png"/> </a>any text
3 any text <img src="https://mydomain.subdomain.com/fixed_word/variable_word1/something.png"/> any text
4 any text <img any-attribute src=\"/fixed_word/variable_word1/something.png"/> any text
5 any text <a any-attribute href=\"/fixed_word/variable_word2/something2.png"><img src=\"/fixed_word/variable_word2/something2.png"/> </a>any text
6 any text <img any-attribute src="https://mydomain.subdomain.com/fixed_word/variable_word6/something6.png"/> any text
OutPut should be:
id article
1 any text <img any-atribute src="https://mydomain.subdomain.com/fixed_word/variable_word1/something.png"/> any text
2 any text <a any-attribute href="https://mydomain.subdomain.com/fixed_word/variable_word2/something2.png"><img src="https://mydomain.subdomain.com/fixed_word/variable_word2/something2.png"/> </a>any text
3 any text <img src="https://mydomain.subdomain.com/fixed_word/variable_word1/something.png"/> any text
4 any text <img any-attribute src="https://mydomain.subdomain.com/fixed_wordvariable_word1/something.png"/> any text
5 any text <a any-attribute href="https://mydomain.subdomain.com/fixed_word/variable_word2/something2.png">
6 any text <img any-attribute src="https://mydomain.subdomain.com/fixed_word/variable_word6/something6.png"/> any text

This can be a starting point:
UPDATE blog_posts
SET article = regexp_replace(
article,
E'(src|href)=[^"]*"/fixed_word/([^"]*)',
E'\\1="https://mydomain.subdomain.com/fixed_word/\\2',
'g'
)
WHERE article ~ E'(src|href)=[^"]*"/fixed_word/([^"]*)';

Related

T-SQL SUBSTRING with CHARINDEX AS LENGTH part is returning too much text

I have ploughed through the massive amount of queries on here relating to SUBSTRING and CHARINDEX but I cannot find one that answers my query.
I am extracting a single part of a long piece of text but it is returning 48 characters too much. E.g. in the first row of the results the length should be 44 characters rather than the 92 characters it is giving. I split out the various parts of the query into the last 3 columns to get the starting position and the length but when I put it together it doesn't work correctly. What am I doing wrong?
My code: (Updated to make consumable I hope)
IF OBJECT_ID('tempdb.dbo.#WQuery', 'U') IS NOT NULL
DROP TABLE #WQuery
CREATE TABLE #WQuery
(
IncidentID VARCHAR(100),
Description VARCHAR(250),
)
INSERT INTO #WQuery
(IncidentID, Description)
VALUES
('B209BBA0-9039-ED11-81AD-0050569FE3BD','<b>Please indicate your company''s export status:</b><br />New to export (less than 1 years experience)<br /><br /><b>What is the destination market for your goods/services?</b><br />United Kingdom<br /><br />'),
('13A75070-0F38-ED11-81AD-0050569FE3BD','<b>Please indicate your company''s export status:</b><br />Novice exporter (1-3 years experience)<br /><br /><b>What is the destination market for your goods/services?</b><br />Kazakhstan <br /><br />'),
('D2926CA8-EB28-ED11-81AC-0050569FE3BD','<b>Please indicate your company''s export status:</b><br />New to export (less than 1 years experience)<br /><br /><b>What is the destination market for your goods/services?</b><br />Zambia (central Africa)<br/'),
('7226B826-DF24-ED11-81AC-0050569FE3BD','<b>Please indicate your company''s export status:</b><br />Experienced exporter (3+ years experience in multiple markets)<br /><br /><b>What is the destination market for your goods/services?</b><br />Spain<br'),
('E636692C-3C22-ED11-81AC-0050569FE3BD','<b>Please indicate your company''s export status:</b><br />New to export (less than 1 years experience)<br /><br /><b>What is the destination market for your goods/services?</b><br />India<br /><br />'),
('C13937A0-EF16-ED11-81AC-0050569FE3BD','<b>Please indicate your company''s export status:</b><br />New to export (less than 1 years experience)<br /><br /><b>What is the destination market for your goods/services?</b><br />Rotterdam<br /><br /><b>')
;
select
i.incidentid
, i.description
, SUBSTRING(i.description,
CHARINDEX('export status:</b><br />', i.description)+LEN('export status:</b><br />'),
CHARINDEX('<br /><br /><b>What is the destination market',i.description) - (CHARINDEX('export status:</b><br />', i.description)-LEN('export status:</b><br />')) ) As ExportStatus
--substring(string,start,length)--
--length is the number of characters to extract - must be positive--
--split the substring above to test the values--
,CHARINDEX('export status:</b><br />', i.description)+LEN('export status:</b><br />') as start
,CHARINDEX('<br /><br /><b>What is the destination market',i.description) as secondQStart
,CHARINDEX('<br /><br /><b>What is the destination market',i.description) - CHARINDEX('export status:</b><br />', i.description)-LEN('export status:</b><br />') as length
--charindex(substring,string,start)--
from #WQuery i
DROP TABLE #WQuery;
The expected results for column 3 (export status) should be:
However I am getting this:
When I added the code from the column 'Length' into the parameter of the SUBSTRING query it gave an error.
Msg 537, Level 16, State 3, Line 3
Invalid length parameter passed to the LEFT or SUBSTRING function.
When I added the brackets around that part of the SUBSTRING the query ran but as you can see it is not returning the same number of characters and the 'length' in the last column.
I am struggling to understand why the length parameter in the SUBSTRING query is not working the same as the same code in the 'length' column. And I also do not understand why the code needs brackets in the parameter of SUBSTRING query to work or throws the error.
Your text is almost valid XHTML. You just need to fix up the ends of the lines in some cases, I assume this is a copy-paste error.
For example, <br />Spain<br should be <br />Spain<br />, and Rotterdam<br /><br /><b> should be Rotterdam<br /><br /><b />.
Now you can just use XQuery to get the right piece of text, which appears to be the first text not enclosed by any node.
SELECT ExportStatus = CAST(wq.Description AS xml).value('(/text())[1]', 'nvarchar(max)')
FROM #WQuery wq
db<>fiddle

PSQL add line breaks to a string

I have a function in PSQL that sends an email to a particular user. The function takes an email text argument and adds this to some constant text before and after in the email body:
In this function, I have a json_build_object call which deals with the recipient, body and title of the email:
jsonb_build_object(
'recipient',recipient,
'title',title,
'message_text', 'some text before.
some text on new line ' || body ||
' some text after.
some text on new line.'
)
My problem is, in the text before and after body, I can't format this on to separate lines. I have tried the following but it did not work:
jsonb_build_object(
'recipient',recipient,
'title',title,
'message_text', E'some text before.\n
some text on new line \n' || body ||
E'\nsome text after.\n
some text on new line.'
)
Can anyone advise what I am doing wrong?
You do it correctly, and the result has line breaks in the form \n. That's how line breaks in text look in JSON.
RFC 8259 describes this:
A string begins and ends with
quotation marks. All Unicode characters may be placed within the
quotation marks, except for the characters that MUST be escaped:
quotation mark, reverse solidus, and the control characters (U+0000
through U+001F).
Line feed is character U+000A, so it must be escaped.
If you want unescaped line breaks, use something else than JSON.
Laurenz Albe pointed out the issue from the JSON end. My answer is about the other end.
What are you doing with the JSON to get it into an email?
It might be possible to do what you want from there. An example in Python:
select * from json_build_object(
'recipient', 'aklaver',
'title', 'head bottlewasher',
'message_text', 'some text before.\nsome text on new line ' || ' The body'||' some text after.\nsome text on new line.'
);
json_build_object
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
{"recipient" : "aklaver", "title" : "head bottlewasher", "message_text" : "some text before.\\nsome text on new line The body some text after.\\nsome text on new line."}
email_str = "some text before.\\nsome text on new line The body some text after.\\nsome text on new line."
print(email_str.replace("\\n", "\n"))
some text before.
some text on new line The body some text after.
some text on new line.

DokuWiki: Side-By-Side diff: Table with two cols in code block in table cell

I want to create a table in DokuWiki which has two rows.
On the left side is a code block (old code), and on the right side there is an other code block (new code).
How to format this in dokuwiki?
If it would be html, it would be easy:
<table>
<tr>
<td>
<pre>
...
</pre>
</td>
<td>
<pre>
...
</pre>
</td>
</tr>
</table>
Optional: Syntax highlighting for Python would be nice.
This should do the work:
| <code>Row 1 Col 1</code> | <code>Row 1 Col 2</code> |
Or for a simple monospaced text use '':
| ''%%Row 1 Col 1%%'' | ''%%Row 1 Col 2%%'' |
EDIT Add %% %% makes string to be not interpreted as DokuWiki syntax.
Here the documentation: https://www.dokuwiki.org/wiki:syntax
||border=1
||!Table heading 1||!Table heading 2||
||Cell 1.1||Cell 1.2||
||Cell 2.1||Cell 2.2||

Show table rownumber

I have a script which type is="text/x-tmpl"
This script generates the rows and columns into the tbody.
What I try to do is to create a column which have a input to show the number of row of each item.
example:
row 1: thumbnail - Filename - 1
row 2: thumbnail - Filenaem - 2
...
...
I want that the user can change his row number.
The problem is that always show "0".
Here is the code:
{% for (var i=0, file; file=o.files[i]; i++) { %}
<tr class="template-upload fade">
<td><input type="text" value="{%=[i]%}"></td> /**My input to show the number of row**/
</tr>
{% } %}

TRIM not works with lines and tabs of a xpath in PostgreSQL?

With this query
SELECT trim(title) FROM (
SELECT
unnest( xpath('//p[#class="secTitle1"]', xmlText )::varchar[] ) AS title
FROM t1
) as t2
and XML input text with lines and spaces,
<root>
...
<p class="x">
text text
text text
</p><p> ...</p>
...
</root>
The trim() have no effect (!). It is a PostgreSQL bug? How to apply fn:normalize-space() with the XPath? I need something like "WHERE title is not null"? (Oracle is simpler...) How to do this simple query with PostreSQL?
Workaround
I need a well-configured build-in function, not a workaround... But I need to work and to show results, so I am using regular expression...
SELECT id, TRIM(regexp_replace(tit, E'[\\n\\r\\t ]+', ' ', 'g')) AS tit
FROM (
SELECT
id, -- xpath returns array of 1, 2, or more strings
unnest( xpath('//p[#class="secTitle1"]', texto )::VARCHAR[] ) AS tit
FROM t
) AS tmp
So, a "only simple space trim" is not friendly, not util (!).
EDIT after #mu comment
I try
SELECT id, TRIM(tit, E'\\n\\r\\t') AS tit
and
SELECT id, TRIM(tit, '\n\r\t') AS tit
both NOT WORKs.
QUESTION REMAINS:
there are no TRIM-option or postgresql configuration to say to TRIM work as it is required?
can I use normalize-space() at xpath? How?
I am using PostgreSQL 9.1, need to upgrade?
It works in 9.2, and it works on 8.4 too.
postgres=# select trim(unnest(string_to_array(e'\t\tHello\n\t\tHello\n\t\tHello', e'\n')), e'\t');
btrim
-------
Hello
Hello
Hello
(3 rows)
your regexp replace any char \n or \r or \t, but trim working with string "\n\r\t". It has different meaning than you expect.